You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by st...@apache.org on 2020/03/18 13:10:00 UTC

[maven] branch mng-5668-poc updated (cabd646 -> 5ed7700)

This is an automated email from the ASF dual-hosted git repository.

stephenc pushed a change to branch mng-5668-poc
in repository https://gitbox.apache.org/repos/asf/maven.git.


 discard cabd646  [MNG-5668] Dynamic component resolution to allow older Maven versions to fail gracefully
 discard a37988a  [MNG-5668] Add a feature experiments framework to allow for opt-in
 discard 016a7d6  [MNG-5668] Add error reporting if the user tries to invoke a dynamic phase directly
 discard 11748bb  [MNG-5668] Fix typo in xsi namespace
 discard 56a8e6e  [MNG-5668] Add some tests
 discard fcd714d  [MNG-5668] Proof of concept implementation of dynamic phases
     add a431794  [MNG-6399] - Lift JDK minimum to JDK 8
     add 6b1c016  Fixed JavaDoc issue.
     add 6f5f1f1  updated GitHub repository description
     add 56d4ea5  added link to documentation
     add 00654c2  [MNG-6810] - Remove profiles in maven-model
     add 0022733  Added .asf.yaml to be ignored by apache-rat-plguin.
     add b810f59  [MNG-6811] - Remove unnecessary filtering configuration
     add f7ca74d  [MNG-6812] - Remove unused files from maven-embedder
     add 2c8f927  Added label apache-maven
     add 25ced83  [MNG-6813] - Remove Maven 1 leftover
     add 610e623  [MNG-6814] - Remove useless exclusion in maven-plugin-api
     add 13c80d5  [MNG-6815] - Upgrade guice 4.2.2
     add 7284bd6  Updated README.md
     add 5750857  [MNG-6817] - Upgrade mockito to 3.2.0
     add 11664b6  [MNG-6818] - Upgrade plexus-utils 3.3.0
     add 3332f4d  [MNG-6816] Prefer System.lineSeparator() over system properties
     add 99953a4  [MNG-6820] - Remove unnecessary dependency exclusions for commons-cli
     add e7654f6  [MNG-6821] - Remove unnecessary dependency exclusions for plexus-component-annotations
     add b8f066e  [MNG-6823] - Remove unnecessary dependency exclusions for wagon-http
     add 06842d6  [MNG-6826] - Remove condition check for JDK8+ in FileSizeFormatTest  - The conditions to check for JDK8+ in test cases is    obsolete with the lift to JDK8.
     add 78ad10d  [MNG-6807] - Remove LifecycleXpp3ReaderTest
     add 370570b  Fixed display text for Apache License.
     add aad48b7  Removed duplication of License part.
     add 11b8b2d  [MNG-6824] ModelMerger is broken Fix modules Apply Java 8 Functions
     add 1ad7801  [MNG-6827] Replace deprecated StringUtils#defaultString() from Plexus Utils
     add e3aa406  [MNG-6824] ModelMerger is broken Fixing reportSet.reports, mailingList.otherArchives, contributor.roles, build.filters, execution.goals, patternSet.includes, patternSet.excludes
     add d251074  [MNG-6065] Create option --fail-on-severity
     add 25de698  Removed JDK7 related configuration.
     add e48c067  Moved org.slf4j.impl.MavenLoggerFactoryTest to the correct submodule
     add 08397c2  [MNG-6065] Moved org.slf4j.impl.MavenLoggerFactoryTest to the correct submodule
     add 5553ff0  [MNG-5982] Pass user properties to ModelBuildingRequest
     add 6d63038  Revert "[MNG-5982] Pass user properties to ModelBuildingRequest"
     add f3e6641  [MNG-6841] update plexus-interpolation to 1.26
     add 735b72f  [MNG-6844] Use StandardCharsets and remove outdated @SuppressWarnings
     add 5670dfa  [MNG-6842] ProjectBuilderTest uses Guava, but Guava is not defined in dependencies
     add f620bb7  [MNG-6844] Remove outdated TODOs
     add 3949228  [MNG-6847] Explicit type can be replaced by the diamond operator
     add 9989e6a  [MNG-6837] Simplify detection of the MAVEN_HOME and make it fully qualified on Windows
     add 838c196  [MNG-5587] When the build fails emit any errors without the user having to specify -e or -X
     add da5d8b8  [MNG-6850] Prevent printing the EXEC_DIR when it's just a disk letter
     add a6f113a  Bump junit from 4.12 to 4.13
     add ce35eff  [MNG-6853] - Don't box primitives where it's not needed
     add ff9bc4f  [MNG-6852] Upgrade maven-source-plugin from 3.2.0 to 3.2.1
     add ddb454a  [MNG-6831] Replace Anonymous classes by lambdas
     add 1697e7a  [MNG-6855] Simplify code
     add ace32fd  [MNG-6855] Simplify code - computeIfAbsent()
     add e6c897e  [MNG-6855] Simplify some code
     add 96e11e1  [MNG-6855] Remove redundant code
     add cdb2cd0  [MNG-6071] Normalize relative paths for working directory
     add 720e46d  Revert "[MNG-5587] When the build fails emit any errors without the user having to specify -e or -X"
     add 45076f3  Improve license handling
     add 35658fd  Run Integration Tests with Java 8, 11, 13 and 14
     add 716cc1f  [MNG-5669] same pom.xml is read multiple times
     add b0d2846  [MNG-6859] Build not reproducible when built from source release
     add d9bf929  [MNG-6562] added WARNING on default bindings plugins unlocked versions
     add 9ae008a  use https://repository.a.o/ for Apache SNAPSHOT plugins
     add f2e9afd  Refactor getLocalRepository() in tests by using the repositorySystem
     add d204f02  [MNG-6874] - Upgrade Maven Parent to 34
     add 9e92a93  [MNG-6872] - Found CVEs in your dependencies - plexus-utils (tests)
     add 5cdb833  [MNG-5669] Fix infinitive loop in case pom.xml is being updated during the process (e.g. maven-shade-plugin writing reduced-pom with excluded dependencies)
     new c107911  [MNG-5668] Proof of concept implementation of dynamic phases
     new cfcd672  [MNG-5668] Add some tests
     new 82be11e  [MNG-5668] Fix typo in xsi namespace
     new b5401e6  [MNG-5668] Add error reporting if the user tries to invoke a dynamic phase directly
     new 71178c5  [MNG-5668] Add a feature experiments framework to allow for opt-in
     new 5ed7700  [MNG-5668] Dynamic component resolution to allow older Maven versions to fail gracefully

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (cabd646)
            \
             N -- N -- N   refs/heads/mng-5668-poc (5ed7700)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .asf.yaml                                          |   9 +
 Jenkinsfile                                        |  10 +-
 README.md                                          |  10 +-
 apache-maven/pom.xml                               |   8 +-
 apache-maven/src/bin/mvn.cmd                       |  12 +-
 .../main/appended-resources/META-INF/LICENSE.vm    |  19 +-
 .../licenses/{ASL-2.0.txt => Apache-2.0.txt}       |   0
 apache-maven/src/main/assembly/component.xml       |   1 +
 .../apache/maven/settings/GlobalSettingsTest.java  |   3 +-
 .../repository/ArtifactRepositoryPolicy.java       |   4 +-
 .../AbstractArtifactResolutionException.java       |   2 +-
 .../MultipleArtifactsNotFoundException.java        |   2 +-
 .../artifact/versioning/ComparableVersion.java     |   6 +-
 .../maven/artifact/versioning/VersionRange.java    |   4 +-
 .../org/apache/maven/building/DefaultProblem.java  |   2 +-
 .../maven/building/DefaultProblemCollector.java    |   2 +-
 .../java/org/apache/maven/building/FileSource.java |  31 ++
 .../org/apache/maven/building/StringSource.java    |  36 +-
 .../java/org/apache/maven/building/UrlSource.java  |  32 +-
 .../artifact/resolver/DefaultArtifactResolver.java |  14 +-
 .../maven/profiles/DefaultProfileManager.java      |  19 +-
 .../java/org/apache/maven/project/ModelUtils.java  |   8 +-
 .../DefaultModelInheritanceAssembler.java          |  10 +-
 .../project/validation/ModelValidationResult.java  |   6 +-
 .../repository/legacy/LegacyRepositorySystem.java  |   8 +-
 .../metadata/DefaultClasspathTransformation.java   |  30 +-
 .../maven/repository/metadata/MetadataGraph.java   |  14 +-
 .../AbstractArtifactComponentTestCase.java         |   3 +-
 .../resolver/ArtifactResolutionExceptionTest.java  |   2 +-
 .../resolver/filter/AndArtifactFilterTest.java     |  10 +-
 .../resolver/filter/OrArtifactFilterTest.java      |  10 +-
 .../maven/artifact/testutils/TestFileManager.java  |  13 +-
 .../maven/repository/legacy/StringWagon.java       |  11 +-
 .../resolver/DefaultArtifactCollectorTest.java     |  20 +-
 maven-core/pom.xml                                 |  37 +-
 .../apache/maven/DuplicateProjectException.java    |   2 +-
 .../main/java/org/apache/maven/ReactorReader.java  |   8 +-
 .../metadata/AbstractRepositoryMetadata.java       |   3 +-
 .../apache/maven/bridge/MavenRepositorySystem.java |   8 +-
 .../maven/classrealm/DefaultClassRealmManager.java |   5 +-
 .../DefaultMavenExecutionRequestPopulator.java     |   2 +-
 .../execution/DefaultMavenExecutionResult.java     |   4 +-
 .../org/apache/maven/execution/ReactorManager.java |  19 +-
 .../scope/internal/MojoExecutionScope.java         |  47 +--
 .../graph/FilteredProjectDependencyGraph.java      |   2 +-
 .../DefaultLifecycleExecutionPlanCalculator.java   |   4 +-
 .../internal/DefaultLifecycleMappingDelegate.java  |   8 +-
 .../internal/DefaultLifecyclePluginAnalyzer.java   |  11 +-
 .../lifecycle/internal/DependencyContext.java      |   4 +-
 .../lifecycle/internal/LifecycleModuleBuilder.java |   3 +-
 .../lifecycle/internal/MojoDescriptorCreator.java  |   2 +-
 .../lifecycle/internal/ReactorBuildStatus.java     |   2 +-
 .../multithreaded/MultiThreadedBuilder.java        |  15 +-
 .../builder/multithreaded/ThreadOutputMuxer.java   |   2 +-
 .../plugin/DefaultLifecycleBindingsInjector.java   |  42 +-
 .../plugin/internal/DefaultMavenPluginManager.java |  10 +-
 .../DefaultPluginDependenciesResolver.java         |  11 +-
 .../PluginDependencyResolutionListener.java        |  10 +-
 .../version/PluginVersionResolutionException.java  |  12 +-
 .../maven/project/DefaultProjectBuilder.java       |  12 +-
 .../DefaultProjectDependenciesResolver.java        |  11 +-
 .../org/apache/maven/project/MavenProject.java     |   2 +-
 .../org/apache/maven/project/ProjectSorter.java    |   8 +-
 .../apache/maven/project/ReactorModelCache.java    |  78 +++-
 .../artifact/DefaultMavenMetadataCache.java        |   8 +-
 .../maven/repository/ArtifactTransferEvent.java    |   5 +-
 .../maven/session/scope/internal/SessionScope.java |  47 +--
 .../maven/toolchain/DefaultToolchainManager.java   |   2 +-
 .../building/DefaultToolchainsBuilder.java         |  17 +-
 .../building/DefaultToolchainsBuildingResult.java  |   2 +-
 .../artifact/handler/ArtifactHandlerTest.java      |   1 -
 .../configuration/DefaultBeanConfiguratorTest.java |  20 +-
 .../scope/internal/MojoExecutionScopeTest.java     |  20 +-
 .../lifecycle/internal/BuilderCommonTest.java      |   3 +-
 .../internal/LifecycleDependencyResolverTest.java  |  10 +-
 .../internal/stub/CompletionServiceStub.java       |   2 +-
 .../internal/stub/DefaultLifecyclesStub.java       |   1 -
 .../lifecycle/internal/stub/MojoExecutorStub.java  |   2 +-
 .../PluginParameterExpressionEvaluatorTest.java    |   2 +-
 .../project/AbstractMavenProjectTestCase.java      |   7 +-
 .../project/DefaultMavenProjectBuilderTest.java    |   6 +-
 .../project/ExtensionDescriptorBuilderTest.java    |  11 +-
 .../apache/maven/project/ProjectBuilderTest.java   |  20 +-
 .../building/DefaultToolchainsBuilderTest.java     |   2 +-
 .../building/ToolchainsBuildingExceptionTest.java  |   2 +-
 .../test/projects/project-builder/MNG-6723/pom.xml |  38 ++
 .../resources-project-builder/micromailer/pom.xml  |   2 +-
 maven-embedder/pom.xml                             |  88 ++---
 .../main/java/org/apache/maven/cli/CLIManager.java |   5 +-
 .../org/apache/maven/cli/CLIReportingUtils.java    |   4 +-
 .../main/java/org/apache/maven/cli/MavenCli.java   |  30 +-
 .../java/org/apache/maven/cli/ResolveFile.java     |   3 +-
 .../maven/cli/event/ExecutionEventLogger.java      |  28 +-
 .../impl/UnsupportedSlf4jBindingConfiguration.java |   2 +-
 .../transfer/AbstractMavenTransferListener.java    |   2 +-
 .../cli/transfer/ConsoleMavenTransferListener.java |   2 +-
 .../META-INF/maven/slf4j-configuration.properties  |   2 +-
 .../src/test/embedder-test-project/pom.xml         |  48 ---
 .../src/main/java/org/apache/maven/App.java        |  13 -
 .../src/test/java/org/apache/maven/AppTest.java    |  38 --
 .../aggregate-mojo-failure/plugin/pom.xml          |  49 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  36 --
 .../aggregate-mojo-failure/project/pom.xml         |  25 --
 .../bad-build-plan/plugin/pom.xml                  |  49 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  35 --
 .../bad-build-plan/project/pom.xml                 |  25 --
 .../bad-dep-version/pom.xml                        |  33 --
 .../test-maven-ext/1/test-maven-ext-1.pom          |  34 --
 .../bad-ext-direct-deps/project/pom.xml            |  35 --
 .../1/bad-ext-plugin-dep-ver-maven-plugin-1.jar    | Bin 3166 -> 0 bytes
 .../1/bad-ext-plugin-dep-ver-maven-plugin-1.pom    |  55 ---
 .../bad-ext-plugin-dep-ver/plugin/pom.xml          |  57 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  33 --
 .../bad-ext-plugin-dep-ver/project/pom.xml         |  37 --
 .../1/bad-ext-plugin-maven-ver-maven-plugin-1.jar  | Bin 3166 -> 0 bytes
 .../1/bad-ext-plugin-maven-ver-maven-plugin-1.pom  |  54 ---
 .../maven-metadata-local.xml                       |  12 -
 .../bad-ext-plugin-maven-ver/plugin/pom.xml        |  57 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  33 --
 .../bad-ext-plugin-maven-ver/project/pom.xml       |  37 --
 .../bad-maven-version/pom.xml                      |  11 -
 .../bad-mg-dep-version/pom.xml                     |  35 --
 .../bad-non-dep-version/pom.xml                    |  35 --
 .../bad-profile-repo/pom.xml                       |   7 -
 .../bad-profile-repo/profiles.xml                  |  18 -
 .../config-rdonly-mojo-param/plugin/pom.xml        |  49 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  39 --
 .../config-rdonly-mojo-param/project/pom.xml       |  47 ---
 .../deploy-repo-creation-err/pom.xml               |  41 --
 .../duplicated-attachments/plugin/pom.xml          |  54 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  50 ---
 .../duplicated-attachments/project/pom.xml         |  25 --
 .../1/err-loading-plugin-maven-plugin-1.jar        | Bin 3166 -> 0 bytes
 .../1/err-loading-plugin-maven-plugin-1.pom        |  55 ---
 .../err-loading-plugin/project/pom.xml             |  45 ---
 .../org/apache/maven/errortest/dep/1/dep-1.pom     |  16 -
 .../1/err-resolving-ext-plugin-maven-plugin-1.jar  | Bin 3166 -> 0 bytes
 .../1/err-resolving-ext-plugin-maven-plugin-1.pom  |  60 ---
 .../err-resolving-ext-plugin/project/pom.xml       |  18 -
 .../org/apache/maven/errortest/dep/1/dep-1.pom     |  16 -
 .../err-resolving-project-dep/project/pom.xml      |  27 --
 .../apache/maven/test/error/mojoFailure/App.java   |  13 -
 .../maven/test/error/mojoFailure/AppTest.java      |  38 --
 .../test-maven-ext-dep/1/test-maven-ext-dep-1.pom  |  26 --
 .../test-maven-ext/1/test-maven-ext-1.pom          |  34 --
 .../ext-deps-resolve-err/project/pom.xml           |  35 --
 .../ext-plugin-artifact-missing-maven-plugin-1.pom |  55 ---
 .../ext-plugin-artifact-missing/project/pom.xml    |  37 --
 .../ext-plugin-realm-error/plugin/pom.xml          |  49 ---
 .../src/main/java/org/plugin/ComponentOne.java     |   8 -
 .../src/main/java/org/plugin/ComponentTwo.java     |   8 -
 .../src/main/java/org/plugin/TestPlugin.java       |  39 --
 .../main/resources/META-INF/plexus/components.xml  |  25 --
 .../ext-plugin-realm-error/project/pom.xml         |  36 --
 .../1/ext-plugin-version-err-maven-plugin-1.jar    | Bin 3166 -> 0 bytes
 .../1/ext-plugin-version-err-maven-plugin-1.pom    |  50 ---
 .../maven-metadata-local.xml                       |  10 -
 .../ext-plugin-version-err/plugin/pom.xml          |  57 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  33 --
 .../ext-plugin-version-err/project/pom.xml         |  36 --
 .../ext-realm-error/ext/pom.xml                    |  38 --
 .../ext/src/main/java/org/ext/App.java             |  13 -
 .../main/resources/META-INF/plexus/components.xml  |   1 -
 .../ext-realm-error/project/pom.xml                |  35 --
 .../interp-from-model/pom.xml                      |   7 -
 .../local-repo/org/test/bad-pom/1/bad-pom-1.pom    |   9 -
 .../interp-from-project/project/pom.xml            |  22 --
 .../load-extern-profiles-ioex/pom.xml              |   7 -
 .../load-extern-profiles-xex/pom.xml               |   7 -
 .../load-extern-profiles-xex/profiles.xml          |   4 -
 .../missing-direct-invoke-mojo/plugin/pom.xml      |  49 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  36 --
 .../missing-module-pom/child1/pom.xml              |  19 -
 .../child1/src/main/java/org/test/App.java         |  13 -
 .../child1/src/test/java/org/test/AppTest.java     |  38 --
 .../missing-module-pom/pom.xml                     |  13 -
 .../missing-parent-pom/pom.xml                     |  11 -
 .../missing-req-mojo-param/plugin/pom.xml          |  49 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  38 --
 .../missing-req-mojo-param/project/pom.xml         |  25 --
 .../mojo-config-error/plugin/pom.xml               |  49 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  33 --
 .../src/main/resources/META-INF/maven/plugin.xml   |  38 --
 .../mojo-config-error/project/pom.xml              |  45 ---
 .../mojo-exec-err/plugin/pom.xml                   |  49 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  33 --
 .../mojo-exec-err/project/pom.xml                  |  26 --
 .../mojo-lookup-err/plugin/pom.xml                 |  54 ---
 .../src/main/java/org/plugin/TestPlugin.java       |  42 --
 .../mojo-lookup-err/project/pom.xml                |  25 --
 .../parent-parse-ioex/child/pom.xml                |  10 -
 .../parent-parse-ioex/pom.xml                      |   0
 .../parent-parse-xex/child/pom.xml                 |  10 -
 .../parent-parse-xex/pom.xml                       |   7 -
 .../profile-activator-err/pom.xml                  |  39 --
 .../profile-activator-lookup-err/ext/pom.xml       |  38 --
 .../ext/src/main/java/org/ext/App.java             |  13 -
 .../main/resources/META-INF/plexus/components.xml  |  16 -
 .../profile-activator-lookup-err/project/pom.xml   |  46 ---
 .../project-collision/mod1/pom.xml                 |   7 -
 .../project-collision/mod2/pom.xml                 |   7 -
 .../project-collision/pom.xml                      |  12 -
 .../project-cycle/dep/pom.xml                      |  12 -
 .../error-reporting-projects/project-cycle/pom.xml |  19 -
 .../project-dep-missing/pom.xml                    |  22 --
 .../apache/maven/test/error/mojoFailure/App.java   |  13 -
 .../maven/test/error/mojoFailure/AppTest.java      |  38 --
 .../project-mojo-failure/pom.xml                   |  17 -
 .../apache/maven/test/error/mojoFailure/App.java   |  14 -
 .../maven/test/error/mojoFailure/AppTest.java      |  38 --
 .../project-parse-xex/pom.xml                      |  25 --
 .../project-validation/pom.xml                     |  13 -
 .../repo-creation-err/pom.xml                      |  41 --
 .../test/eventing-projects/read-with-deps/pom.xml  |  15 -
 .../read-with-deps/repo/tests/dep/1/dep-1.pom      |   6 -
 .../eventing-projects/simple-read-project/pom.xml  |   6 -
 .../test/extensions/META-INF/plexus/components.xml |  28 --
 .../maven/cli/CLIManagerDocumentationTest.java     |   2 +-
 .../maven/cli/transfer/FileSizeFormatTest.java     |  21 +-
 .../src/test/plugin-version-references/jar-pom.xml |  32 --
 .../plugin-version-references/maven-plugin-pom.xml |  36 --
 .../bad-module-non-recursive/badmodule/pom.xml     |  14 -
 .../bad-module-non-recursive/goodmodule/pom.xml    |  14 -
 .../test/projects/bad-module-non-recursive/pom.xml |  14 -
 .../src/test/projects/invalid-goal/pom.xml         |  49 ---
 .../project/pom.xml                                |  13 -
 .../src/main/java/org/codehaus/m2eclipse/App.java  |  13 -
 .../test/java/org/codehaus/m2eclipse/AppTest.java  |  38 --
 .../parent/1.0-SNAPSHOT/maven-metadata-company.xml |  11 -
 .../parent/1.0-SNAPSHOT/parent-1.0-SNAPSHOT.pom    |  18 -
 .../m2eclipse/parent/maven-metadata-local.xml      |  11 -
 .../settings.xml                                   |  23 --
 .../src/test/projects/optional-dep/pom.xml         |  20 -
 .../readProject-missingModuleIgnored/pom.xml       |  13 -
 .../modules/child1/pom.xml                         |  13 -
 .../readProject-withScmInheritance/pom.xml         |  19 -
 .../org.apache.maven/maven-core/pom.properties     |  18 -
 .../resources/pom-with-distribution-status.xml     |  30 --
 .../test/resources/pom-without-dependencies.xml    |  30 --
 maven-embedder/src/test/resources/pom.xml          |  34 --
 maven-embedder/src/test/resources/pom2.xml         |  48 ---
 .../test/resources/settings/invalid-settings.xml   |  24 --
 .../src/test/resources/settings/valid-settings.xml |  27 --
 .../maven/model/building/ArtifactModelSource.java  |  27 +-
 .../maven/model/building/DefaultModelBuilder.java  | 242 ++++++++----
 .../maven/model/building/FileModelSource.java      |   9 +-
 .../model/building/ModelBuildingEventCatapult.java |   9 +-
 .../apache/maven/model/building/ModelCache.java    |  29 ++
 .../apache/maven/model/building/ModelCacheTag.java |  26 ++
 .../inheritance/DefaultInheritanceAssembler.java   |   8 +-
 .../interpolation/ProblemDetectingValueSource.java |   1 -
 .../StringSearchModelInterpolator.java             |  32 +-
 .../StringVisitorModelInterpolator.java            |  32 +-
 .../DefaultDependencyManagementInjector.java       |   4 +-
 .../DefaultPluginManagementInjector.java           |   8 +-
 .../apache/maven/model/merge/MavenModelMerger.java |  48 +--
 .../model/profile/DefaultProfileInjector.java      |  16 +-
 .../model/superpom/DefaultSuperPomProvider.java    |   2 +-
 .../model/validation/DefaultModelValidator.java    |   7 +-
 maven-model-builder/src/main/mdo/profiles.mdo      | 399 -------------------
 .../StringSearchModelInterpolatorTest.java         |  20 +-
 maven-model/pom.xml                                |  58 +--
 .../org/apache/maven/model/merge/ModelMerger.java  | 408 +++++--------------
 .../apache/maven/model/merge/ModelMergerTest.java  | 430 +++++++++++++++++++++
 maven-plugin-api/pom.xml                           |   6 -
 .../plugin/lifecycle/LifecycleXpp3ReaderTest.java  |  55 ---
 maven-plugin-api/src/test/resources/lifecycle.xml  |  39 --
 .../internal/DefaultArtifactDescriptorReader.java  |   7 +-
 .../repository/internal/DefaultModelResolver.java  |   7 +-
 .../internal/RemoteSnapshotMetadataTest.java       |   2 +-
 .../settings/building/DefaultSettingsBuilder.java  |  17 +-
 .../building/DefaultSettingsBuildingResult.java    |   2 +-
 .../building/DefaultSettingsProblemCollector.java  |   2 +-
 .../crypto/DefaultSettingsDecryptionResult.java    |   6 +-
 maven-slf4j-provider/pom.xml                       |   4 +
 .../org/slf4j/impl/MavenFailOnSeverityLogger.java  | 142 +++++++
 ...eLoggerFactory.java => MavenLoggerFactory.java} |  43 ++-
 .../java/org/slf4j/impl/MavenSimpleLogger.java     |  24 +-
 .../java/org/slf4j/impl/StaticLoggerBinder.java    |   4 +-
 .../org/slf4j/impl/MavenLoggerFactoryTest.java     |  90 +++++
 {maven-feature => maven-slf4j-wrapper}/pom.xml     |  18 +-
 .../apache/maven/logwrapper/LogLevelRecorder.java  |  41 +-
 .../maven/logwrapper/MavenSlf4jWrapperFactory.java |  17 +-
 .../src/site/site.xml                              |   0
 .../maven/logwrapper/LogLevelRecorderTest.java     |  37 +-
 pom.xml                                            |  63 ++-
 286 files changed, 1844 insertions(+), 5705 deletions(-)
 create mode 100644 .asf.yaml
 rename apache-maven/src/main/appended-resources/licenses/{ASL-2.0.txt => Apache-2.0.txt} (100%)
 delete mode 100644 maven-embedder/src/test/embedder-test-project/pom.xml
 delete mode 100644 maven-embedder/src/test/embedder-test-project/src/main/java/org/apache/maven/App.java
 delete mode 100644 maven-embedder/src/test/embedder-test-project/src/test/java/org/apache/maven/AppTest.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/aggregate-mojo-failure/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/aggregate-mojo-failure/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/aggregate-mojo-failure/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-build-plan/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-build-plan/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-build-plan/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-dep-version/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-direct-deps/local-repo/org/apache/maven/errortest/test-maven-ext/1/test-maven-ext-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-direct-deps/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-dep-ver/local-repo/org/apache/maven/errortest/bad-ext-plugin-dep-ver-maven-plugin/1/bad-ext-plugin-dep-ver-maven-plugin-1.jar
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-dep-ver/local-repo/org/apache/maven/errortest/bad-ext-plugin-dep-ver-maven-plugin/1/bad-ext-plugin-dep-ver-maven-plugin-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-dep-ver/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-dep-ver/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-dep-ver/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-maven-ver/local-repo/org/apache/maven/errortest/bad-ext-plugin-maven-ver-maven-plugin/1/bad-ext-plugin-maven-ver-maven-plugin-1.jar
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-maven-ver/local-repo/org/apache/maven/errortest/bad-ext-plugin-maven-ver-maven-plugin/1/bad-ext-plugin-maven-ver-maven-plugin-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-maven-ver/local-repo/org/apache/maven/errortest/bad-ext-plugin-maven-ver-maven-plugin/maven-metadata-local.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-maven-ver/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-maven-ver/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-maven-ver/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-maven-version/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-mg-dep-version/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-non-dep-version/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-profile-repo/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/bad-profile-repo/profiles.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/config-rdonly-mojo-param/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/config-rdonly-mojo-param/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/config-rdonly-mojo-param/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/deploy-repo-creation-err/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/duplicated-attachments/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/duplicated-attachments/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/duplicated-attachments/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-loading-plugin/local-repo/org/apache/maven/errortest/err-loading-plugin-maven-plugin/1/err-loading-plugin-maven-plugin-1.jar
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-loading-plugin/local-repo/org/apache/maven/errortest/err-loading-plugin-maven-plugin/1/err-loading-plugin-maven-plugin-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-loading-plugin/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-ext-plugin/local-repo/org/apache/maven/errortest/dep/1/dep-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-ext-plugin/local-repo/org/apache/maven/errortest/err-resolving-ext-plugin-maven-plugin/1/err-resolving-ext-plugin-maven-plugin-1.jar
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-ext-plugin/local-repo/org/apache/maven/errortest/err-resolving-ext-plugin-maven-plugin/1/err-resolving-ext-plugin-maven-plugin-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-ext-plugin/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-project-dep/project/local-repo/org/apache/maven/errortest/dep/1/dep-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-project-dep/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-project-dep/project/src/main/java/org/apache/maven/test/error/mojoFailure/App.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/err-resolving-project-dep/project/src/test/java/org/apache/maven/test/error/mojoFailure/AppTest.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-deps-resolve-err/local-repo/org/apache/maven/errortest/test-maven-ext-dep/1/test-maven-ext-dep-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-deps-resolve-err/local-repo/org/apache/maven/errortest/test-maven-ext/1/test-maven-ext-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-deps-resolve-err/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-artifact-missing/local-repo/org/apache/maven/errortest/ext-plugin-artifact-missing-maven-plugin/1/ext-plugin-artifact-missing-maven-plugin-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-artifact-missing/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-realm-error/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-realm-error/plugin/src/main/java/org/plugin/ComponentOne.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-realm-error/plugin/src/main/java/org/plugin/ComponentTwo.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-realm-error/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-realm-error/plugin/src/main/resources/META-INF/plexus/components.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-realm-error/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-version-err/local-repo/org/apache/maven/errortest/ext-plugin-version-err-maven-plugin/1/ext-plugin-version-err-maven-plugin-1.jar
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-version-err/local-repo/org/apache/maven/errortest/ext-plugin-version-err-maven-plugin/1/ext-plugin-version-err-maven-plugin-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-version-err/local-repo/org/apache/maven/errortest/ext-plugin-version-err-maven-plugin/maven-metadata-local.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-version-err/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-version-err/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-plugin-version-err/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-realm-error/ext/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-realm-error/ext/src/main/java/org/ext/App.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-realm-error/ext/src/main/resources/META-INF/plexus/components.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/ext-realm-error/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/interp-from-model/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/interp-from-project/project/local-repo/org/test/bad-pom/1/bad-pom-1.pom
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/interp-from-project/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/load-extern-profiles-ioex/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/load-extern-profiles-xex/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/load-extern-profiles-xex/profiles.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-direct-invoke-mojo/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-direct-invoke-mojo/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-module-pom/child1/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-module-pom/child1/src/main/java/org/test/App.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-module-pom/child1/src/test/java/org/test/AppTest.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-module-pom/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-parent-pom/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-req-mojo-param/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-req-mojo-param/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/missing-req-mojo-param/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-config-error/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-config-error/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-config-error/plugin/src/main/resources/META-INF/maven/plugin.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-config-error/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-exec-err/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-exec-err/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-exec-err/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-lookup-err/plugin/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-lookup-err/plugin/src/main/java/org/plugin/TestPlugin.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/mojo-lookup-err/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/parent-parse-ioex/child/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/parent-parse-ioex/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/parent-parse-xex/child/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/parent-parse-xex/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/profile-activator-err/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/profile-activator-lookup-err/ext/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/profile-activator-lookup-err/ext/src/main/java/org/ext/App.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/profile-activator-lookup-err/ext/src/main/resources/META-INF/plexus/components.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/profile-activator-lookup-err/project/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-collision/mod1/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-collision/mod2/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-collision/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-cycle/dep/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-cycle/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-dep-missing/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-dep-missing/src/main/java/org/apache/maven/test/error/mojoFailure/App.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-dep-missing/src/test/java/org/apache/maven/test/error/mojoFailure/AppTest.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-mojo-failure/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-mojo-failure/src/main/java/org/apache/maven/test/error/mojoFailure/App.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-mojo-failure/src/test/java/org/apache/maven/test/error/mojoFailure/AppTest.java
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-parse-xex/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/project-validation/pom.xml
 delete mode 100644 maven-embedder/src/test/error-reporting-projects/repo-creation-err/pom.xml
 delete mode 100644 maven-embedder/src/test/eventing-projects/read-with-deps/pom.xml
 delete mode 100644 maven-embedder/src/test/eventing-projects/read-with-deps/repo/tests/dep/1/dep-1.pom
 delete mode 100644 maven-embedder/src/test/eventing-projects/simple-read-project/pom.xml
 delete mode 100644 maven-embedder/src/test/extensions/META-INF/plexus/components.xml
 delete mode 100644 maven-embedder/src/test/plugin-version-references/jar-pom.xml
 delete mode 100644 maven-embedder/src/test/plugin-version-references/maven-plugin-pom.xml
 delete mode 100644 maven-embedder/src/test/projects/bad-module-non-recursive/badmodule/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/bad-module-non-recursive/goodmodule/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/bad-module-non-recursive/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/invalid-goal/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/isolated-project-getting-parent-pom/project/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/isolated-project-getting-parent-pom/project/src/main/java/org/codehaus/m2eclipse/App.java
 delete mode 100644 maven-embedder/src/test/projects/isolated-project-getting-parent-pom/project/src/test/java/org/codehaus/m2eclipse/AppTest.java
 delete mode 100644 maven-embedder/src/test/projects/isolated-project-getting-parent-pom/repository/org/codehaus/m2eclipse/parent/1.0-SNAPSHOT/maven-metadata-company.xml
 delete mode 100644 maven-embedder/src/test/projects/isolated-project-getting-parent-pom/repository/org/codehaus/m2eclipse/parent/1.0-SNAPSHOT/parent-1.0-SNAPSHOT.pom
 delete mode 100644 maven-embedder/src/test/projects/isolated-project-getting-parent-pom/repository/org/codehaus/m2eclipse/parent/maven-metadata-local.xml
 delete mode 100644 maven-embedder/src/test/projects/isolated-project-getting-parent-pom/settings.xml
 delete mode 100644 maven-embedder/src/test/projects/optional-dep/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/readProject-missingModuleIgnored/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/readProject-withScmInheritance/modules/child1/pom.xml
 delete mode 100644 maven-embedder/src/test/projects/readProject-withScmInheritance/pom.xml
 delete mode 100644 maven-embedder/src/test/resources/META-INF/maven/org.apache.maven/maven-core/pom.properties
 delete mode 100644 maven-embedder/src/test/resources/pom-with-distribution-status.xml
 delete mode 100644 maven-embedder/src/test/resources/pom-without-dependencies.xml
 delete mode 100644 maven-embedder/src/test/resources/pom.xml
 delete mode 100644 maven-embedder/src/test/resources/pom2.xml
 delete mode 100644 maven-embedder/src/test/resources/settings/invalid-settings.xml
 delete mode 100644 maven-embedder/src/test/resources/settings/valid-settings.xml
 copy maven-core/src/main/java/org/apache/maven/plugin/version/PluginVersionNotFoundException.java => maven-model-builder/src/main/java/org/apache/maven/model/building/ArtifactModelSource.java (69%)
 delete mode 100644 maven-model-builder/src/main/mdo/profiles.mdo
 create mode 100644 maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java
 delete mode 100644 maven-plugin-api/src/test/java/org/apache/maven/plugin/lifecycle/LifecycleXpp3ReaderTest.java
 delete mode 100644 maven-plugin-api/src/test/resources/lifecycle.xml
 create mode 100644 maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenFailOnSeverityLogger.java
 rename maven-slf4j-provider/src/main/java/org/slf4j/impl/{MavenSimpleLoggerFactory.java => MavenLoggerFactory.java} (52%)
 create mode 100644 maven-slf4j-provider/src/test/java/org/slf4j/impl/MavenLoggerFactoryTest.java
 copy {maven-feature => maven-slf4j-wrapper}/pom.xml (70%)
 copy maven-core/src/main/java/org/apache/maven/extension/internal/CoreExportsProvider.java => maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/LogLevelRecorder.java (52%)
 copy maven-core/src/main/java/org/apache/maven/classrealm/ClassRealmManagerDelegate.java => maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/MavenSlf4jWrapperFactory.java (70%)
 copy {maven-slf4j-provider => maven-slf4j-wrapper}/src/site/site.xml (100%)
 copy maven-compat/src/main/java/org/apache/maven/repository/metadata/MetadataGraphTransformationException.java => maven-slf4j-wrapper/src/test/java/org/apache/maven/logwrapper/LogLevelRecorderTest.java (55%)


[maven] 06/06: [MNG-5668] Dynamic component resolution to allow older Maven versions to fail gracefully

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stephenc pushed a commit to branch mng-5668-poc
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 5ed7700b52610e3e242e269fe11ed3ef427aad97
Author: Stephen Connolly <st...@gmail.com>
AuthorDate: Sat Nov 23 10:47:46 2019 +0000

    [MNG-5668] Dynamic component resolution to allow older Maven versions to fail gracefully
    
    Example on a project that has the experimental features enabled:
    
        $ mvn -version
        Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T19:33:14+01:00)
        Maven home: /usr/local/Cellar/maven/3.5.4/libexec
        Java version: 1.8.0_152, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/jre
        Default locale: en_IE, platform encoding: UTF-8
        OS name: "mac os x", version: "10.14.6", arch: "x86_64", family: "mac"
        $ mvn validate
        [ERROR] The project uses experimental features that require exactly Maven 3.7.0-SNAPSHOT -> [Help 1]
        [ERROR]
        [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
        [ERROR] Re-run Maven using the -X switch to enable full debug logging.
        [ERROR]
        [ERROR] For more information about the errors and possible solutions, please read the following articles:
        [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MavenExecutionException
---
 .../org/apache/maven/feature/check/Helper.java     | 50 ++++++++++++++++++++++
 .../feature/check/MavenExperimentEnabler.java      | 25 +++--------
 2 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/maven-experiments/src/main/java/org/apache/maven/feature/check/Helper.java b/maven-experiments/src/main/java/org/apache/maven/feature/check/Helper.java
new file mode 100644
index 0000000..eda0433
--- /dev/null
+++ b/maven-experiments/src/main/java/org/apache/maven/feature/check/Helper.java
@@ -0,0 +1,50 @@
+package org.apache.maven.feature.check;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.feature.api.MavenFeatures;
+import org.apache.maven.feature.spi.DefaultMavenFeatures;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+
+/**
+ * Helper class to work around class scanning/loading issues.
+ */
+class Helper
+{
+    static void enableFeatures( MavenSession session, String targetVersion, PlexusContainer container,
+                                File topLevelProjectFile )
+        throws MavenExecutionException, ClassNotFoundException, ComponentLookupException
+    {
+        MavenFeatures features = container.lookup( MavenFeatures.class, "default" );
+        if ( !( features instanceof DefaultMavenFeatures ) )
+        {
+            throw new MavenExecutionException(
+                "This project uses experimental features that require exactly Maven " + targetVersion
+                    + ", cannot enable experimental features because feature flag component is not as expected (was: "
+                    + features + ")", topLevelProjectFile );
+        }
+        ( (DefaultMavenFeatures) features ).enable( session );
+    }
+}
diff --git a/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java b/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
index 26e2ee4..4ef526c 100644
--- a/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
+++ b/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
@@ -32,10 +32,10 @@ import org.apache.maven.AbstractMavenLifecycleParticipant;
 import org.apache.maven.Maven;
 import org.apache.maven.MavenExecutionException;
 import org.apache.maven.execution.MavenSession;
-import org.apache.maven.feature.api.MavenFeatures;
-import org.apache.maven.feature.spi.DefaultMavenFeatures;
+import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 import org.codehaus.plexus.logging.Logger;
 
 /**
@@ -49,8 +49,8 @@ public class MavenExperimentEnabler
     @Requirement
     private Logger log;
 
-    @Requirement( role = MavenFeatures.class, hint = "default", optional = true )
-    private MavenFeatures features;
+    @Requirement
+    private PlexusContainer container;
 
     private final Map<MavenSession, Void> startedSessions = new WeakHashMap<>();
 
@@ -112,9 +112,9 @@ public class MavenExperimentEnabler
         }
         try
         {
-            enableFeatures( session, targetVersion );
+            Helper.enableFeatures( session, targetVersion, this.container, this.topLevelProjectFile( session ) );
         }
-        catch ( LinkageError e )
+        catch ( LinkageError | ClassNotFoundException | ComponentLookupException e )
         {
             throw new MavenExecutionException(
                 "The project uses experimental features that require exactly Maven " + targetVersion,
@@ -122,19 +122,6 @@ public class MavenExperimentEnabler
         }
     }
 
-    private void enableFeatures( MavenSession session, String targetVersion )
-        throws MavenExecutionException
-    {
-        if ( !( features instanceof DefaultMavenFeatures ) )
-        {
-            throw new MavenExecutionException(
-                "This project uses experimental features that require exactly Maven " + targetVersion
-                    + ", cannot enable experimental features because feature flag component is not as expected (was: "
-                    + features + ")", topLevelProjectFile( session ) );
-        }
-        ( (DefaultMavenFeatures) features ).enable( session );
-    }
-
     private File topLevelProjectFile( MavenSession session )
     {
         return session.getTopLevelProject() != null ? session.getTopLevelProject().getFile() : null;


[maven] 05/06: [MNG-5668] Add a feature experiments framework to allow for opt-in

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stephenc pushed a commit to branch mng-5668-poc
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 71178c5d0307601665e9d4e3662101890266f6a5
Author: Stephen Connolly <st...@gmail.com>
AuthorDate: Fri Nov 22 15:46:35 2019 +0000

    [MNG-5668] Add a feature experiments framework to allow for opt-in
    
    Users get to turn on all experiments (no partial activation) by adding the experiments extension to `.mvn/extensions.xml`, e.g.
    
        <?xml version="1.0" encoding="UTF-8"?>
        <extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
          <extension>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-experiments</artifactId>
            <version>3.7.0-SNAPSHOT</version>
          </extension>
        </extensions>
    
    Without the extension, the dynamic phases feature is disabled
    
    With the extension the feature is enabled, e.g.
    
        [INFO] Enabling experimental features of Maven 3.7.0-SNAPSHOT
        [INFO] Experimental features enabled:
        [INFO]   * dynamic-phases
        [INFO] Scanning for projects...
    
    Attempts to build the project with a different (newer) version of Maven will
    fail, e.g.
    
        [ERROR] The project uses experimental features that require exactly Maven 3.7.0-SNAPSHOT -> [Help 1]
        [ERROR]
        [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
        [ERROR] Re-run Maven using the -X switch to enable full debug logging.
        [ERROR]
        [ERROR] For more information about the errors and possible solutions, please read the following articles:
        [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MavenExecutionException
    
    Attempts to build the project with a different (older) version of Maven
    will blow up due to class not found (I'd like to determine how to lazy
    resolve from Plexus/Sisu to avoid that)
---
 maven-core/pom.xml                                 |   4 +
 .../org/apache/maven/execution/MavenSession.java   |   3 +-
 .../maven/feature/spi/DefaultMavenFeatures.java    | 130 ++++++++++++++++
 .../internal/DefaultLifecycleMappingDelegate.java  |  31 ++--
 .../DefaultLifecycleTaskSegmentCalculator.java     |  12 +-
 .../maven/lifecycle/internal/MojoExecutor.java     |  12 +-
 .../maven/lifecycle/internal/PhaseRecorder.java    |  32 +++-
 .../main/resources/META-INF/plexus/components.xml  |  11 ++
 .../lifecycle/internal/PhaseRecorderTest.java      |   2 +-
 maven-experiments/pom.xml                          |  59 ++++++++
 .../feature/check/MavenExperimentEnabler.java      | 164 +++++++++++++++++++++
 maven-feature/pom.xml                              |  44 ++++++
 .../maven/feature/api/MavenFeatureContext.java     |  30 ++++
 .../apache/maven/feature/api/MavenFeatures.java    |  39 +++++
 pom.xml                                            |  12 ++
 15 files changed, 563 insertions(+), 22 deletions(-)

diff --git a/maven-core/pom.xml b/maven-core/pom.xml
index 7a723a2..76bbd0d 100644
--- a/maven-core/pom.xml
+++ b/maven-core/pom.xml
@@ -50,6 +50,10 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
+      <artifactId>maven-feature</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
       <artifactId>maven-builder-support</artifactId>
     </dependency>
     <dependency>
diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
index 5b56df3..0671326 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
@@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.repository.RepositoryCache;
+import org.apache.maven.feature.api.MavenFeatureContext;
 import org.apache.maven.monitor.event.EventDispatcher;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.project.MavenProject;
@@ -44,7 +45,7 @@ import org.eclipse.aether.RepositorySystemSession;
  * @author Jason van Zyl
  */
 public class MavenSession
-    implements Cloneable
+    implements Cloneable, MavenFeatureContext
 {
     private MavenExecutionRequest request;
 
diff --git a/maven-core/src/main/java/org/apache/maven/feature/spi/DefaultMavenFeatures.java b/maven-core/src/main/java/org/apache/maven/feature/spi/DefaultMavenFeatures.java
new file mode 100644
index 0000000..93070cc
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/feature/spi/DefaultMavenFeatures.java
@@ -0,0 +1,130 @@
+package org.apache.maven.feature.spi;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.feature.api.MavenFeatureContext;
+import org.apache.maven.feature.api.MavenFeatures;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
+ * <p>
+ * Feature flags for experiments. There is no partial opt-in, you get all the feature that are in turned on in the
+ * current version of Maven if you activate the experiments extension and none of the features if you don't.
+ *
+ * <h2>How we use this</h2>
+ * <ul>
+ * <li>When starting work on a feature, add a constant string to this class to hold the feature name.</li>
+ * <li>When ready to expose the experiment, add the feature name to {@code META-INF/plexus/components.xml}.</li>
+ * <li>When the experiment has been concluded, remove the feature name and collapse whatever branch logic was based
+ *  * on the feature flag.</li>
+ * </ul>
+ */
+@Component( role = MavenFeatures.class, hint = "default" )
+public class DefaultMavenFeatures
+    implements MavenFeatures
+{
+    /**
+     * The feature name of dynamic phases.
+     */
+    public static final String DYNAMIC_PHASES = "dynamic-phases";
+
+    @Requirement
+    private Logger log;
+
+    /**
+     * The contexts that are enabled.
+     */
+    private final Map<MavenFeatureContext, Boolean> enabled = new WeakHashMap<>();
+
+    /**
+     * The current experimental features being exposed to opt-in builds.
+     */
+    private Set<String> features;
+
+    public DefaultMavenFeatures()
+    {
+        this.features = Collections.<String>emptySet();
+    }
+
+    public List<String> getFeatures()
+    {
+        return features == null ? Collections.<String>emptyList() : new ArrayList<String>( features );
+    }
+
+    public void setFeatures( List<String> features )
+    {
+        this.features = features == null ? Collections.<String>emptySet() : new HashSet<String>( features );
+    }
+
+    /**
+     * Enabled the feature context. This method is only to be invoked by {@code MavenExperimentEnabler}.
+     *
+     * @param context the context to enable.
+     * @throws MavenExecutionException if we detect illegal usage.
+     *                                 {@code MavenExperimentEnabler}.
+     */
+    public void enable( MavenFeatureContext context )
+        throws MavenExecutionException
+    {
+        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+        for ( StackTraceElement element : Thread.currentThread().getStackTrace() )
+        {
+            if ( "org.apache.maven.feature.check.MavenExperimentEnabler".equals( element.getClassName() ) )
+            {
+                enabled.put( context, Boolean.TRUE );
+                log.info( "Experimental features enabled:" );
+                for ( String feature: new TreeSet<>( features ) )
+                {
+                    log.info( "  * " + feature );
+                }
+                return;
+            }
+        }
+        throw new MavenExecutionException( "Detected illegal attempt to bypass experimental feature activation",
+                                           (File) null );
+    }
+
+    @Override
+    public boolean enabled( MavenFeatureContext context, String featureName )
+    {
+        if ( Boolean.TRUE.equals( enabled.get( context ) ) )
+        {
+            return features != null && features.contains( featureName );
+        }
+        else
+        {
+            return false;
+        }
+    }
+}
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java
index a8c6c4b..6a5050b 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java
@@ -19,7 +19,15 @@ package org.apache.maven.lifecycle.internal;
  * under the License.
  */
 
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.feature.api.MavenFeatures;
+import org.apache.maven.feature.spi.DefaultMavenFeatures;
 import org.apache.maven.lifecycle.Lifecycle;
 import org.apache.maven.lifecycle.LifecycleMappingDelegate;
 import org.apache.maven.model.Plugin;
@@ -36,12 +44,6 @@ import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
 
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
 /**
  * Lifecycle mapping delegate component interface. Calculates project build execution plan given {@link Lifecycle} and
  * lifecycle phase. Standard lifecycles use plugin execution {@code <phase>} or mojo default lifecycle phase to
@@ -56,6 +58,9 @@ public class DefaultLifecycleMappingDelegate
     @Requirement
     private BuildPluginManager pluginManager;
 
+    @Requirement
+    private MavenFeatures features;
+
     public Map<String, List<MojoExecution>> calculateLifecycleMappings( MavenSession session, MavenProject project,
                                                                         Lifecycle lifecycle, String lifecyclePhase )
         throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
@@ -66,8 +71,12 @@ public class DefaultLifecycleMappingDelegate
          * is interested in, i.e. all phases up to and including the specified phase.
          */
 
+        boolean dynamicPhasesEnabled = features.enabled( session, DefaultMavenFeatures.DYNAMIC_PHASES );
+
         Map<String, Map<Integer, List<MojoExecution>>> mappings =
-            new TreeMap<>( new PhaseComparator( lifecycle.getPhases() ) );
+            dynamicPhasesEnabled
+                ? new TreeMap<String, Map<Integer, List<MojoExecution>>>( new PhaseComparator( lifecycle.getPhases() ) )
+                : new LinkedHashMap<String, Map<Integer, List<MojoExecution>>>();
 
         for ( String phase : lifecycle.getPhases() )
         {
@@ -97,7 +106,9 @@ public class DefaultLifecycleMappingDelegate
                 if ( execution.getPhase() != null )
                 {
                     Map<Integer, List<MojoExecution>> phaseBindings =
-                        getPhaseBindings( mappings, execution.getPhase() );
+                        dynamicPhasesEnabled
+                            ? getPhaseBindings( mappings, execution.getPhase() )
+                            : mappings.get( execution.getPhase() );
                     if ( phaseBindings != null )
                     {
                         for ( String goal : execution.getGoals() )
@@ -118,7 +129,9 @@ public class DefaultLifecycleMappingDelegate
                                                              session.getRepositorySession() );
 
                         Map<Integer, List<MojoExecution>> phaseBindings =
-                            getPhaseBindings( mappings, mojoDescriptor.getPhase() );
+                            dynamicPhasesEnabled
+                                ? getPhaseBindings( mappings, mojoDescriptor.getPhase() )
+                                : mappings.get( mojoDescriptor.getPhase() );
                         if ( phaseBindings != null )
                         {
                             MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java
index c10cbf0..6f950c3 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java
@@ -20,6 +20,8 @@ package org.apache.maven.lifecycle.internal;
  */
 
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.feature.api.MavenFeatures;
+import org.apache.maven.feature.spi.DefaultMavenFeatures;
 import org.apache.maven.lifecycle.LifecycleNotFoundException;
 import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
 import org.apache.maven.plugin.InvalidPluginDescriptorException;
@@ -45,11 +47,11 @@ import java.util.List;
  * </p>
  * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
  *
- * @since 3.0
  * @author Benjamin Bentmann
  * @author Jason van Zyl
  * @author jdcasey
  * @author Kristian Rosenvold (extracted class)
+ * @since 3.0
  */
 @Component( role = LifecycleTaskSegmentCalculator.class )
 public class DefaultLifecycleTaskSegmentCalculator
@@ -61,6 +63,9 @@ public class DefaultLifecycleTaskSegmentCalculator
     @Requirement
     private LifecyclePluginResolver lifecyclePluginResolver;
 
+    @Requirement
+    private MavenFeatures features;
+
     public DefaultLifecycleTaskSegmentCalculator()
     {
     }
@@ -96,7 +101,7 @@ public class DefaultLifecycleTaskSegmentCalculator
         {
             PhaseId phaseId = PhaseId.of( task );
             // if the priority is non-zero then you specified the priority on the CLI
-            if ( phaseId.priority() != 0 )
+            if ( phaseId.priority() != 0 && features.enabled( session, DefaultMavenFeatures.DYNAMIC_PHASES ) )
             {
                 throw new LifecyclePhaseNotFoundException(
                     "Dynamic phases such as \"" + task + "\" are only permitted as execution targets specified "
@@ -125,7 +130,8 @@ public class DefaultLifecycleTaskSegmentCalculator
                 }
                 catch ( NoPluginFoundForPrefixException e )
                 {
-                    if ( phaseId.executionPoint() != PhaseExecutionPoint.AS && phaseId.phase().indexOf( ':' ) == -1 )
+                    if ( phaseId.executionPoint() != PhaseExecutionPoint.AS && phaseId.phase().indexOf( ':' ) == -1
+                        && features.enabled( session, DefaultMavenFeatures.DYNAMIC_PHASES ) )
                     {
                         LifecyclePhaseNotFoundException lpnfe = new LifecyclePhaseNotFoundException(
                             "Dynamic phases such as \"" + task + "\" are only permitted as execution targets specified "
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
index ae5b03f..f1ed605 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
@@ -24,6 +24,8 @@ import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.artifact.resolver.filter.CumulativeScopeArtifactFilter;
 import org.apache.maven.execution.ExecutionEvent;
 import org.apache.maven.execution.MavenSession;
+import org.apache.maven.feature.api.MavenFeatures;
+import org.apache.maven.feature.spi.DefaultMavenFeatures;
 import org.apache.maven.lifecycle.LifecycleExecutionException;
 import org.apache.maven.lifecycle.MissingProjectException;
 import org.apache.maven.plugin.BuildPluginManager;
@@ -77,6 +79,9 @@ public class MojoExecutor
     @Requirement
     private ExecutionEventCatapult eventCatapult;
 
+    @Requirement
+    private MavenFeatures features;
+
     public MojoExecutor()
     {
     }
@@ -142,7 +147,8 @@ public class MojoExecutor
     {
         DependencyContext dependencyContext = newDependencyContext( session, mojoExecutions );
 
-        PhaseRecorder phaseRecorder = new PhaseRecorder( session.getCurrentProject() );
+        boolean dynamicPhasesEnabled = features.enabled( session, DefaultMavenFeatures.DYNAMIC_PHASES );
+        PhaseRecorder phaseRecorder = new PhaseRecorder( session.getCurrentProject(), dynamicPhasesEnabled );
 
         Iterator<MojoExecution> iterator = mojoExecutions.iterator();
         try
@@ -155,6 +161,10 @@ public class MojoExecutor
         }
         catch ( LifecycleExecutionException failure )
         {
+            if ( !dynamicPhasesEnabled )
+            {
+                throw failure;
+            }
             // run any post: executions for the current phase
             while ( iterator.hasNext() )
             {
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java
index c76f22f..ae5b63e 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java
@@ -35,9 +35,12 @@ public class PhaseRecorder
 
     private final MavenProject project;
 
-    public PhaseRecorder( MavenProject project )
+    private final boolean dynamicPhasesEnabled;
+
+    public PhaseRecorder( MavenProject project, boolean dynamicPhasesEnabled )
     {
         this.project = project;
+        this.dynamicPhasesEnabled = dynamicPhasesEnabled;
     }
 
     public void observeExecution( MojoExecution mojoExecution )
@@ -46,15 +49,30 @@ public class PhaseRecorder
 
         if ( lifecyclePhase != null )
         {
-            PhaseId phaseId = PhaseId.of( lifecyclePhase );
-            if ( lastLifecyclePhase == null )
+            if ( dynamicPhasesEnabled )
             {
-                lastLifecyclePhase = phaseId.phase();
+                PhaseId phaseId = PhaseId.of( lifecyclePhase );
+                if ( lastLifecyclePhase == null )
+                {
+                    lastLifecyclePhase = phaseId.phase();
+                }
+                else if ( !phaseId.phase().equals( lastLifecyclePhase ) )
+                {
+                    project.addLifecyclePhase( lastLifecyclePhase );
+                    lastLifecyclePhase = phaseId.phase();
+                }
             }
-            else if ( !phaseId.phase().equals( lastLifecyclePhase ) )
+            else
             {
-                project.addLifecyclePhase( lastLifecyclePhase );
-                lastLifecyclePhase = phaseId.phase();
+                if ( lastLifecyclePhase == null )
+                {
+                    lastLifecyclePhase = lifecyclePhase;
+                }
+                else if ( !lifecyclePhase.equals( lastLifecyclePhase ) )
+                {
+                    project.addLifecyclePhase( lastLifecyclePhase );
+                    lastLifecyclePhase = lifecyclePhase;
+                }
             }
         }
 
diff --git a/maven-core/src/main/resources/META-INF/plexus/components.xml b/maven-core/src/main/resources/META-INF/plexus/components.xml
index 3f099cb..c8ff8d5 100644
--- a/maven-core/src/main/resources/META-INF/plexus/components.xml
+++ b/maven-core/src/main/resources/META-INF/plexus/components.xml
@@ -130,5 +130,16 @@ under the License.
         <_configuration-file>~/.m2/settings-security.xml</_configuration-file>
       </configuration>
     </component>
+
+    <component>
+      <role>org.apache.maven.feature.api.MavenFeatures</role>
+      <role-hint>default</role-hint>
+      <implementation>org.apache.maven.feature.spi.DefaultMavenFeatures</implementation>
+      <configuration>
+        <features>
+          <feature>dynamic-phases</feature>
+        </features>
+      </configuration>
+    </component>
   </components>
 </component-set>
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseRecorderTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseRecorderTest.java
index f3d6422..6603bac 100644
--- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseRecorderTest.java
+++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseRecorderTest.java
@@ -30,7 +30,7 @@ import java.util.List;
 public class PhaseRecorderTest extends TestCase
 {
     public void testObserveExecution() throws Exception {
-        PhaseRecorder phaseRecorder = new PhaseRecorder( ProjectDependencyGraphStub.A);
+        PhaseRecorder phaseRecorder = new PhaseRecorder( ProjectDependencyGraphStub.A, false );
         MavenExecutionPlan plan = LifecycleExecutionPlanCalculatorStub.getProjectAExceutionPlan();
         final List<MojoExecution> executions = plan.getMojoExecutions();
 
diff --git a/maven-experiments/pom.xml b/maven-experiments/pom.xml
new file mode 100644
index 0000000..228f10b
--- /dev/null
+++ b/maven-experiments/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.maven</groupId>
+    <artifactId>maven</artifactId>
+    <version>3.7.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>maven-experiments</artifactId>
+
+  <name>Maven Experiments</name>
+  <description>A build extension that enabled the experimental features in the current version of Maven</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-component-metadata</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java b/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
new file mode 100644
index 0000000..26e2ee4
--- /dev/null
+++ b/maven-experiments/src/main/java/org/apache/maven/feature/check/MavenExperimentEnabler.java
@@ -0,0 +1,164 @@
+package org.apache.maven.feature.check;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.WeakHashMap;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.maven.AbstractMavenLifecycleParticipant;
+import org.apache.maven.Maven;
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.feature.api.MavenFeatures;
+import org.apache.maven.feature.spi.DefaultMavenFeatures;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * Enforces that the required version of Maven is running and enables the experimental features of that version.
+ */
+@Component( role = AbstractMavenLifecycleParticipant.class, hint = "experimental" )
+public class MavenExperimentEnabler
+    extends AbstractMavenLifecycleParticipant
+{
+
+    @Requirement
+    private Logger log;
+
+    @Requirement( role = MavenFeatures.class, hint = "default", optional = true )
+    private MavenFeatures features;
+
+    private final Map<MavenSession, Void> startedSessions = new WeakHashMap<>();
+
+    @Override
+    public void afterProjectsRead( MavenSession session )
+        throws MavenExecutionException
+    {
+        if ( !startedSessions.containsKey( session ) )
+        {
+            log.error( "Experimental features cannot be enabled using project/build/extensions" );
+            throw new MavenExecutionException( "Experimental features cannot be enabled using project/build/extensions",
+                                               topLevelProjectFile( session ) );
+        }
+    }
+
+    @Override
+    public void afterSessionStart( MavenSession session )
+        throws MavenExecutionException
+    {
+        startedSessions.put( session, null );
+        log.debug( "Determining experimental feature version requirements" );
+        String targetVersion;
+        try
+        {
+            targetVersion = parse( getClass(), "/META-INF/maven/org.apache.maven/maven-experiments/pom.properties" );
+        }
+        catch ( IOException e )
+        {
+            throw new MavenExecutionException(
+                "Cannot determine required version of Maven to enable experimental features",
+                topLevelProjectFile( session ) );
+        }
+        if ( StringUtils.isBlank( targetVersion ) )
+        {
+            throw new MavenExecutionException(
+                "Cannot determine required version of Maven to enable experimental features",
+                topLevelProjectFile( session ) );
+        }
+        String activeVersion;
+        try
+        {
+            activeVersion = parse( Maven.class, "/META-INF/maven/org.apache.maven/maven-core/pom.properties" );
+        }
+        catch ( IOException e )
+        {
+            throw new MavenExecutionException( "Cannot confirm executing version of Maven as " + targetVersion
+                                                   + " which is required to enable the experimental features used"
+                                                   + " by this project", topLevelProjectFile( session ) );
+        }
+        if ( Objects.equals( activeVersion, targetVersion ) )
+        {
+            log.info( "Enabling experimental features of Maven " + targetVersion );
+        }
+        else
+        {
+            throw new MavenExecutionException(
+                "The project uses experimental features that require exactly Maven " + targetVersion,
+                topLevelProjectFile( session ) );
+        }
+        try
+        {
+            enableFeatures( session, targetVersion );
+        }
+        catch ( LinkageError e )
+        {
+            throw new MavenExecutionException(
+                "The project uses experimental features that require exactly Maven " + targetVersion,
+                topLevelProjectFile( session ) );
+        }
+    }
+
+    private void enableFeatures( MavenSession session, String targetVersion )
+        throws MavenExecutionException
+    {
+        if ( !( features instanceof DefaultMavenFeatures ) )
+        {
+            throw new MavenExecutionException(
+                "This project uses experimental features that require exactly Maven " + targetVersion
+                    + ", cannot enable experimental features because feature flag component is not as expected (was: "
+                    + features + ")", topLevelProjectFile( session ) );
+        }
+        ( (DefaultMavenFeatures) features ).enable( session );
+    }
+
+    private File topLevelProjectFile( MavenSession session )
+    {
+        return session.getTopLevelProject() != null ? session.getTopLevelProject().getFile() : null;
+    }
+
+    private static String parse( Class<?> clazz, String resource )
+        throws IOException
+    {
+        Properties targetProperties = new Properties();
+        try ( InputStream is = clazz.getResourceAsStream( resource ) )
+        {
+            if ( is != null )
+            {
+                targetProperties.load( is );
+            }
+        }
+        return targetProperties.getProperty( "version" );
+    }
+
+    @Override
+    public void afterSessionEnd( MavenSession session )
+        throws MavenExecutionException
+    {
+        startedSessions.remove( session );
+    }
+
+}
diff --git a/maven-feature/pom.xml b/maven-feature/pom.xml
new file mode 100644
index 0000000..6e540f0
--- /dev/null
+++ b/maven-feature/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.maven</groupId>
+    <artifactId>maven</artifactId>
+    <version>3.7.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>maven-feature</artifactId>
+
+  <name>Maven Feature</name>
+  <description>Feature Flags for Maven Core</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/maven-feature/src/main/java/org/apache/maven/feature/api/MavenFeatureContext.java b/maven-feature/src/main/java/org/apache/maven/feature/api/MavenFeatureContext.java
new file mode 100644
index 0000000..e1b0fdb
--- /dev/null
+++ b/maven-feature/src/main/java/org/apache/maven/feature/api/MavenFeatureContext.java
@@ -0,0 +1,30 @@
+package org.apache.maven.feature.api;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+/**
+ * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
+ *
+ * Defines the context within which a features are evaluated.
+ */
+public interface MavenFeatureContext
+{
+}
diff --git a/maven-feature/src/main/java/org/apache/maven/feature/api/MavenFeatures.java b/maven-feature/src/main/java/org/apache/maven/feature/api/MavenFeatures.java
new file mode 100644
index 0000000..2e9222f
--- /dev/null
+++ b/maven-feature/src/main/java/org/apache/maven/feature/api/MavenFeatures.java
@@ -0,0 +1,39 @@
+package org.apache.maven.feature.api;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
+ *
+ * An API to allow making assertions about the presence of specific features in Maven core.
+ * Features are identified using string constants and are only intended for use in opt-in experiments.
+ * Unknown features will always be reported as disabled.
+ */
+public interface MavenFeatures
+{
+    /**
+     * Returns {@code true} if and only if the specified feature is enabled.
+     *
+     * @param context     the context within which to check the feature.
+     * @param featureName the name of the feature.
+     * @return {@code true} if and only if the specified feature is enabled.
+     */
+    boolean enabled( MavenFeatureContext context, String featureName );
+}
diff --git a/pom.xml b/pom.xml
index ef2764d..a5bb34d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,6 +84,7 @@ under the License.
     <module>maven-plugin-api</module>
     <module>maven-builder-support</module>
     <module>maven-model</module>
+    <module>maven-feature</module>
     <module>maven-model-builder</module>
     <module>maven-core</module>
     <module>maven-settings</module>
@@ -95,6 +96,7 @@ under the License.
     <module>maven-slf4j-wrapper</module>
     <module>maven-embedder</module>
     <module>maven-compat</module>
+    <module>maven-experiments</module>
     <module>apache-maven</module>
   </modules>
 
@@ -181,6 +183,16 @@ under the License.
       </dependency>
       <dependency>
         <groupId>org.apache.maven</groupId>
+        <artifactId>maven-experiments</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven</groupId>
+        <artifactId>maven-feature</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.maven</groupId>
         <artifactId>maven-settings</artifactId>
         <version>${project.version}</version>
       </dependency>


[maven] 02/06: [MNG-5668] Add some tests

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stephenc pushed a commit to branch mng-5668-poc
in repository https://gitbox.apache.org/repos/asf/maven.git

commit cfcd672d57ecbb02f2f8c971a2f6e0bda538690f
Author: Stephen Connolly <st...@gmail.com>
AuthorDate: Mon Nov 11 19:27:39 2019 +0000

    [MNG-5668] Add some tests
---
 .../apache/maven/lifecycle/internal/PhaseId.java   |   2 +-
 .../lifecycle/internal/PhaseComparatorTest.java    |  42 ++++++++
 .../maven/lifecycle/internal/PhaseIdTest.java      | 114 +++++++++++++++++++++
 3 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
index 646ac56..a225541 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
@@ -107,7 +107,7 @@ public class PhaseId
             int priorityEnd = phase.lastIndexOf( ']' );
             boolean havePriority;
             int priority;
-            if ( priorityEnd < phaseEnd + 1 )
+            if ( priorityEnd < phaseEnd + 1 || priorityEnd != phase.length() - 1 )
             {
                 priority = 0;
                 havePriority = false;
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseComparatorTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseComparatorTest.java
new file mode 100644
index 0000000..a6fc853
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseComparatorTest.java
@@ -0,0 +1,42 @@
+package org.apache.maven.lifecycle.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+public class PhaseComparatorTest
+    extends TestCase
+{
+    public void testSmokes() throws Exception {
+        PhaseComparator comparator = new PhaseComparator( Arrays.asList( "site", "site-deploy" ) );
+        assertTrue( comparator.compare( "site", "site-deploy" ) < 0);
+        assertTrue( comparator.compare( "site-deploy", "site" ) > 0);
+        assertTrue( comparator.compare( "site", "site" ) == 0);
+        assertTrue( comparator.compare( "site", "deploy" ) < 0);
+        assertTrue( comparator.compare( "before:site", "site" ) < 0);
+        assertTrue( comparator.compare( "after:site", "site-deploy" ) < 0);
+        assertTrue( comparator.compare( "after:site", "site" ) > 0);
+        assertTrue( comparator.compare( "site", "site[1]" ) > 0);
+        assertTrue( comparator.compare( "site", "site[-1]" ) < 0);
+        assertTrue( comparator.compare( "site[1000]", "site[500]" ) < 0);
+    }
+}
diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseIdTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseIdTest.java
new file mode 100644
index 0000000..9a27a82
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/PhaseIdTest.java
@@ -0,0 +1,114 @@
+package org.apache.maven.lifecycle.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+public class PhaseIdTest
+    extends TestCase
+{
+    public void testStaticDefaultPhasesParse()
+        throws Exception
+    {
+        for ( String phase : Arrays.asList( "validate", "initialize", "generate-sources", "process-sources",
+                                            "generate-resources", "process-resources", "compile", "process-classes",
+                                            "generate-test-sources", "process-test-sources", "generate-test-resources",
+                                            "process-test-resources", "test-compile", "process-test-classes", "test",
+                                            "prepare-package", "package", "pre-integration-test", "integration-test",
+                                            "post-integration-test", "verify", "install", "deploy" ) )
+        {
+            assertEquals( phase, PhaseId.of( phase ).phase() );
+            assertEquals( 0, PhaseId.of( phase ).priority() );
+            assertEquals( PhaseExecutionPoint.AS, PhaseId.of( phase ).executionPoint() );
+        }
+    }
+
+    public void testStaticSitePhasesParse()
+        throws Exception
+    {
+        for ( String phase : Arrays.asList( "pre-site", "site", "post-site", "site-deploy" ) )
+        {
+            assertEquals( phase, PhaseId.of( phase ).phase() );
+            assertEquals( 0, PhaseId.of( phase ).priority() );
+            assertEquals( PhaseExecutionPoint.AS, PhaseId.of( phase ).executionPoint() );
+        }
+    }
+
+    public void testStaticCleanPhasesParse()
+        throws Exception
+    {
+        for ( String phase : Arrays.asList( "pre-clean", "clean", "post-clean" ) )
+        {
+            assertEquals( phase, PhaseId.of( phase ).phase() );
+            assertEquals( 0, PhaseId.of( phase ).priority() );
+            assertEquals( PhaseExecutionPoint.AS, PhaseId.of( phase ).executionPoint() );
+        }
+    }
+
+    public void testDynamicPhasesParse()
+    {
+        assertEquals( "verify", PhaseId.of( "before:verify[1000]" ).phase() );
+        assertEquals( "verify", PhaseId.of( "after:verify[1000]" ).phase() );
+        assertEquals( "verify", PhaseId.of( "verify[1000]" ).phase() );
+        assertEquals( PhaseExecutionPoint.BEFORE, PhaseId.of( "before:verify[1000]" ).executionPoint() );
+        assertEquals( PhaseExecutionPoint.AFTER, PhaseId.of( "after:verify[1000]" ).executionPoint() );
+        assertEquals( PhaseExecutionPoint.AS, PhaseId.of( "verify[1000]" ).executionPoint() );
+        assertEquals( 1000, PhaseId.of( "before:verify[1000]" ).priority() );
+        assertEquals( 1000, PhaseId.of( "after:verify[1000]" ).priority() );
+        assertEquals( 1000, PhaseId.of( "verify[1000]" ).priority() );
+        assertEquals( -1000, PhaseId.of( "before:verify[-1000]" ).priority() );
+        assertEquals( -1000, PhaseId.of( "after:verify[-1000]" ).priority() );
+        assertEquals( -1000, PhaseId.of( "verify[-1000]" ).priority() );
+        assertEquals( "verify", PhaseId.of( "before:verify" ).phase() );
+        assertEquals( "verify", PhaseId.of( "after:verify" ).phase() );
+        assertEquals( PhaseExecutionPoint.BEFORE, PhaseId.of( "before:verify" ).executionPoint() );
+        assertEquals( PhaseExecutionPoint.AFTER, PhaseId.of( "after:verify" ).executionPoint() );
+        assertEquals( 0, PhaseId.of( "before:verify" ).priority() );
+        assertEquals( 0, PhaseId.of( "after:verify" ).priority() );
+    }
+
+    public void testInvalidPhasesParseAsUnknown()
+    {
+        for ( String phase : Arrays.asList( "pre:verify", "before-verify", "BEFORE:verify", "verify(1000)",
+                                            "verify[1000", "verify(1000]", "verify[1.0]", "verify[[1000]",
+                                            "verify[1000]]", "[before]verify[1000]", "[1000]verify:before" ) )
+        {
+            assertEquals( phase, PhaseId.of( phase ).phase() );
+            assertEquals( PhaseExecutionPoint.AS, PhaseId.of( phase ).executionPoint() );
+            assertEquals( 0, PhaseId.of( phase ).priority() );
+        }
+        // a valid prefix gets extracted even if the priority fails to parse
+        for ( String phase : Arrays.asList( "before:verify[1000", "before:verify[1.0]", "before:verify(1000]" ) )
+        {
+            assertEquals( phase.substring( 7 ), PhaseId.of( phase ).phase() );
+            assertEquals( PhaseExecutionPoint.BEFORE, PhaseId.of( phase ).executionPoint() );
+            assertEquals( 0, PhaseId.of( phase ).priority() );
+        }
+        // a valid priority gets extracted even if the prefix fails to parse
+        for ( String phase : Arrays.asList( "beFore:verify[1000]", "before-verify[1000]", "pre:verify[1000]" ) )
+        {
+            assertEquals( phase.replace( "[1000]", "" ), PhaseId.of( phase ).phase() );
+            assertEquals( PhaseExecutionPoint.AS, PhaseId.of( phase ).executionPoint() );
+            assertEquals( 1000, PhaseId.of( phase ).priority() );
+        }
+    }
+}


[maven] 03/06: [MNG-5668] Fix typo in xsi namespace

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stephenc pushed a commit to branch mng-5668-poc
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 82be11e585910f8c5ff20fd10b912e131d3409e9
Author: Stephen Connolly <st...@gmail.com>
AuthorDate: Mon Nov 11 21:17:56 2019 +0000

    [MNG-5668] Fix typo in xsi namespace
---
 maven-plugin-api/src/main/mdo/lifecycle.mdo | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/maven-plugin-api/src/main/mdo/lifecycle.mdo b/maven-plugin-api/src/main/mdo/lifecycle.mdo
index b86fde8..8c6922f 100644
--- a/maven-plugin-api/src/main/mdo/lifecycle.mdo
+++ b/maven-plugin-api/src/main/mdo/lifecycle.mdo
@@ -18,7 +18,7 @@ under the License.
 -->
 
 <model xmlns="http://codehaus-plexus.github.io/MODELLO/1.8.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="https://codehaus-plexus.github.io/MODELLO/1.8.0 https://codehaus-plexus.github.io/modello/xsd/modello-1.8.0.xsd"
+  xsi:schemaLocation="http://codehaus-plexus.github.io/MODELLO/1.8.0 https://codehaus-plexus.github.io/modello/xsd/modello-1.8.0.xsd"
   xml.namespace="http://maven.apache.org/LIFECYCLE/${version}"
   xml.schemaLocation="http://maven.apache.org/xsd/lifecycle-${version}.xsd">
   <id>lifecycle-mappings</id>


[maven] 01/06: [MNG-5668] Proof of concept implementation of dynamic phases

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stephenc pushed a commit to branch mng-5668-poc
in repository https://gitbox.apache.org/repos/asf/maven.git

commit c107911816f4b62ca5f2c9ca883ad336bf856976
Author: Stephen Connolly <st...@gmail.com>
AuthorDate: Mon Nov 11 18:46:52 2019 +0000

    [MNG-5668] Proof of concept implementation of dynamic phases
---
 .../internal/DefaultLifecycleMappingDelegate.java  |  38 +++-
 .../maven/lifecycle/internal/MojoExecutor.java     |  49 +++++-
 .../maven/lifecycle/internal/PhaseComparator.java  |  84 +++++++++
 .../lifecycle/internal/PhaseExecutionPoint.java    |  54 ++++++
 .../apache/maven/lifecycle/internal/PhaseId.java   | 196 +++++++++++++++++++++
 .../maven/lifecycle/internal/PhaseRecorder.java    |  12 +-
 maven-plugin-api/src/main/mdo/lifecycle.mdo        |  62 ++++++-
 7 files changed, 474 insertions(+), 21 deletions(-)

diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java
index 892e4f1..a8c6c4b 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleMappingDelegate.java
@@ -19,12 +19,6 @@ package org.apache.maven.lifecycle.internal;
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.lifecycle.Lifecycle;
 import org.apache.maven.lifecycle.LifecycleMappingDelegate;
@@ -42,6 +36,12 @@ import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
 
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
 /**
  * Lifecycle mapping delegate component interface. Calculates project build execution plan given {@link Lifecycle} and
  * lifecycle phase. Standard lifecycles use plugin execution {@code <phase>} or mojo default lifecycle phase to
@@ -67,7 +67,7 @@ public class DefaultLifecycleMappingDelegate
          */
 
         Map<String, Map<Integer, List<MojoExecution>>> mappings =
-            new LinkedHashMap<>();
+            new TreeMap<>( new PhaseComparator( lifecycle.getPhases() ) );
 
         for ( String phase : lifecycle.getPhases() )
         {
@@ -96,7 +96,8 @@ public class DefaultLifecycleMappingDelegate
                 // to examine the phase it is associated to.
                 if ( execution.getPhase() != null )
                 {
-                    Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( execution.getPhase() );
+                    Map<Integer, List<MojoExecution>> phaseBindings =
+                        getPhaseBindings( mappings, execution.getPhase() );
                     if ( phaseBindings != null )
                     {
                         for ( String goal : execution.getGoals() )
@@ -116,7 +117,8 @@ public class DefaultLifecycleMappingDelegate
                             pluginManager.getMojoDescriptor( plugin, goal, project.getRemotePluginRepositories(),
                                                              session.getRepositorySession() );
 
-                        Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( mojoDescriptor.getPhase() );
+                        Map<Integer, List<MojoExecution>> phaseBindings =
+                            getPhaseBindings( mappings, mojoDescriptor.getPhase() );
                         if ( phaseBindings != null )
                         {
                             MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
@@ -146,6 +148,24 @@ public class DefaultLifecycleMappingDelegate
 
     }
 
+    private Map<Integer, List<MojoExecution>> getPhaseBindings( Map<String, Map<Integer, List<MojoExecution>>> mappings,
+                                                                String phase )
+    {
+        Map<Integer, List<MojoExecution>> result = mappings.get( phase );
+        if ( result == null )
+        {
+            // check if this is related to an phase in the plan (pre/post or different priority)
+            PhaseId id = PhaseId.of( phase );
+            if ( mappings.containsKey( id.phase() ) )
+            {
+                // lazy add the phases we need
+                result = new TreeMap<>();
+                mappings.put( phase, result );
+            }
+        }
+        return result;
+    }
+
     private void addMojoExecution( Map<Integer, List<MojoExecution>> phaseBindings, MojoExecution mojoExecution,
                                    int priority )
     {
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
index b78f54d..df3f34c 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
@@ -44,6 +44,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -143,9 +144,50 @@ public class MojoExecutor
 
         PhaseRecorder phaseRecorder = new PhaseRecorder( session.getCurrentProject() );
 
-        for ( MojoExecution mojoExecution : mojoExecutions )
+        Iterator<MojoExecution> iterator = mojoExecutions.iterator();
+        try
         {
-            execute( session, mojoExecution, projectIndex, dependencyContext, phaseRecorder );
+            while ( iterator.hasNext() )
+            {
+                MojoExecution mojoExecution = iterator.next();
+                execute( session, mojoExecution, projectIndex, dependencyContext, phaseRecorder );
+            }
+        }
+        catch ( LifecycleExecutionException failure )
+        {
+            // run any post: executions for the current phase
+            while ( iterator.hasNext() )
+            {
+                MojoExecution mojoExecution = iterator.next();
+                String lifecyclePhase = mojoExecution.getLifecyclePhase();
+                if ( lifecyclePhase == null )
+                {
+                    // we have reached an execution that is not bound to a phase, thus there is no post: for last
+                    // executed phase
+                    break;
+                }
+                if ( phaseRecorder.isDifferentPhase( mojoExecution ) )
+                {
+                    // this is a different phase from the last executed phase, thus no more post:
+                    break;
+                }
+                PhaseId phaseId = PhaseId.of( lifecyclePhase );
+                if ( phaseId.executionPoint() != PhaseExecutionPoint.AFTER )
+                {
+                    // only interested in post: executions
+                    continue;
+                }
+                try
+                {
+                    execute( session, mojoExecution, projectIndex, dependencyContext, phaseRecorder );
+                }
+                catch ( LifecycleExecutionException postFailure )
+                {
+                    // failures are tagged as suppressed
+                    failure.addSuppressed( postFailure );
+                }
+            }
+            throw failure;
         }
     }
 
@@ -209,8 +251,7 @@ public class MojoExecutor
             {
                 pluginManager.executeMojo( session, mojoExecution );
             }
-            catch ( MojoFailureException | PluginManagerException | PluginConfigurationException
-                | MojoExecutionException e )
+            catch ( MojoFailureException | PluginManagerException | PluginConfigurationException | MojoExecutionException e )
             {
                 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
             }
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseComparator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseComparator.java
new file mode 100644
index 0000000..3670c28
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseComparator.java
@@ -0,0 +1,84 @@
+package org.apache.maven.lifecycle.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Compares phases within the context of a specific lifecycle with secondary sorting based on the {@link PhaseId}.
+ */
+public class PhaseComparator
+    implements Comparator<String>
+{
+    /**
+     * The lifecycle phase ordering.
+     */
+    private final List<String> lifecyclePhases;
+
+    /**
+     * Constructor.
+     *
+     * @param lifecyclePhases the lifecycle phase ordering.
+     */
+    public PhaseComparator( List<String> lifecyclePhases )
+    {
+        this.lifecyclePhases = lifecyclePhases;
+    }
+
+    @Override
+    public int compare( String o1, String o2 )
+    {
+        PhaseId p1 = PhaseId.of( o1 );
+        PhaseId p2 = PhaseId.of( o2 );
+        int i1 = lifecyclePhases.indexOf( p1.phase() );
+        int i2 = lifecyclePhases.indexOf( p2.phase() );
+        if ( i1 == -1 && i2 == -1 )
+        {
+            // unknown phases, leave in existing order
+            return 0;
+        }
+        if ( i1 == -1 )
+        {
+            // second one is known, so it comes first
+            return 1;
+        }
+        if ( i2 == -1 )
+        {
+            // first one is known, so it comes first
+            return -1;
+        }
+        int rv = Integer.compare( i1, i2 );
+        if ( rv != 0 )
+        {
+            return rv;
+        }
+        // same phase, now compare execution points
+        i1 = p1.executionPoint().ordinal();
+        i2 = p2.executionPoint().ordinal();
+        rv = Integer.compare( i1, i2 );
+        if ( rv != 0 )
+        {
+            return rv;
+        }
+        // same execution point, now compare priorities (highest wins, so invert)
+        return -Integer.compare( p1.priority(), p2.priority() );
+    }
+}
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseExecutionPoint.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseExecutionPoint.java
new file mode 100644
index 0000000..65313a5
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseExecutionPoint.java
@@ -0,0 +1,54 @@
+package org.apache.maven.lifecycle.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Represents where a dynamic phase should be executed within a static phase.
+ */
+public enum PhaseExecutionPoint
+{
+    /**
+     * Execution must occur before any executions of the phase proper. Failure of any {@link #BEFORE} dynamic phase
+     * execution will prevent the {@link #AS} phase but will not prevent any {@link #AFTER} dynamic phases.
+     */
+    BEFORE( "before:" ),
+    /**
+     * Execution is the execution of the phase proper. Failure of any {@link #AS} dynamic phase execution will fail
+     * the phase. Any {@link #AFTER} phases will still be execution.
+     */
+    AS( "" ),
+    /**
+     * Guaranteed execution dynamic phases on completion of the static phase. All {@link #AFTER} dynamic phases will
+     * be executed provided at least one {@link #BEFORE} or {@link #AS} dynamic phase has started execution.
+     */
+    AFTER( "after:" );
+
+    private final String prefix;
+
+    PhaseExecutionPoint( String prefix )
+    {
+        this.prefix = prefix;
+    }
+
+    public String prefix()
+    {
+        return prefix;
+    }
+}
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
new file mode 100644
index 0000000..646ac56
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
@@ -0,0 +1,196 @@
+package org.apache.maven.lifecycle.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * Represents a parsed phase identifier.
+ */
+public class PhaseId
+{
+    /**
+     * Interned {@link PhaseId} instances.
+     */
+    private static final Map<String, PhaseId> instances = new WeakHashMap<>();
+
+    /**
+     * The execution point of this {@link PhaseId}.
+     */
+    private final PhaseExecutionPoint executionPoint;
+
+    /**
+     * The static phase that this dynamic phase belongs to.
+     */
+    private final String phase;
+
+    /**
+     * The priority of this dynamic phase within the static phase.
+     */
+    private final int priority;
+
+    /**
+     * Parses the phase identifier.
+     *
+     * @param phase the phase identifier.
+     * @return the {@link PhaseId}.
+     */
+    public static synchronized PhaseId of( String phase )
+    {
+        PhaseId result = instances.get( phase );
+        if ( result == null )
+        {
+            result = new PhaseId( phase );
+            instances.put( phase, result );
+        }
+        return result;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param phase the phase identifier string.
+     */
+    private PhaseId( String phase )
+    {
+        int executionPointEnd = phase.indexOf( ':' );
+        int phaseStart;
+        if ( executionPointEnd == -1 )
+        {
+            executionPoint = PhaseExecutionPoint.AS;
+            phaseStart = 0;
+        }
+        else
+        {
+            switch ( phase.substring( 0, executionPointEnd ) )
+            {
+                case "before":
+                    executionPoint = PhaseExecutionPoint.BEFORE;
+                    phaseStart = executionPointEnd + 1;
+                    break;
+                case "after":
+                    executionPoint = PhaseExecutionPoint.AFTER;
+                    phaseStart = executionPointEnd + 1;
+                    break;
+                default:
+                    executionPoint = PhaseExecutionPoint.AS;
+                    phaseStart = 0;
+                    break;
+            }
+        }
+        int phaseEnd = phase.indexOf( '[' );
+        if ( phaseEnd == -1 )
+        {
+            priority = 0;
+            this.phase = phase.substring( phaseStart );
+        }
+        else
+        {
+            int priorityEnd = phase.lastIndexOf( ']' );
+            boolean havePriority;
+            int priority;
+            if ( priorityEnd < phaseEnd + 1 )
+            {
+                priority = 0;
+                havePriority = false;
+            }
+            else
+            {
+                try
+                {
+                    priority = Integer.parseInt( phase.substring( phaseEnd + 1, priorityEnd ) );
+                    havePriority = true;
+                }
+                catch ( NumberFormatException e )
+                {
+                    // priority must be an integer
+                    priority = 0;
+                    havePriority = false;
+                }
+            }
+            if ( havePriority )
+            {
+                this.phase = phase.substring( phaseStart, phaseEnd );
+                this.priority = priority;
+            }
+            else
+            {
+                this.phase = phase.substring( phaseStart );
+                this.priority = 0;
+            }
+        }
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        PhaseId phaseId = (PhaseId) o;
+
+        if ( priority() != phaseId.priority() )
+        {
+            return false;
+        }
+        if ( executionPoint() != phaseId.executionPoint() )
+        {
+            return false;
+        }
+        return phase().equals( phaseId.phase() );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = executionPoint().hashCode();
+        result = 31 * result + phase().hashCode();
+        result = 31 * result + priority();
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        return executionPoint().prefix() + phase() + ( priority() != 0 ? "[" + priority() + ']' : "" );
+    }
+
+    public PhaseExecutionPoint executionPoint()
+    {
+        return executionPoint;
+    }
+
+    public String phase()
+    {
+        return phase;
+    }
+
+    public int priority()
+    {
+        return priority;
+    }
+}
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java
index 3316c50..c76f22f 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseRecorder.java
@@ -24,9 +24,10 @@ import org.apache.maven.project.MavenProject;
 
 /**
  * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
- * @since 3.0
+ *
  * @author Benjamin Bentmann
  * @author Kristian Rosenvold
+ * @since 3.0
  */
 public class PhaseRecorder
 {
@@ -45,14 +46,15 @@ public class PhaseRecorder
 
         if ( lifecyclePhase != null )
         {
+            PhaseId phaseId = PhaseId.of( lifecyclePhase );
             if ( lastLifecyclePhase == null )
             {
-                lastLifecyclePhase = lifecyclePhase;
+                lastLifecyclePhase = phaseId.phase();
             }
-            else if ( !lifecyclePhase.equals( lastLifecyclePhase ) )
+            else if ( !phaseId.phase().equals( lastLifecyclePhase ) )
             {
                 project.addLifecyclePhase( lastLifecyclePhase );
-                lastLifecyclePhase = lifecyclePhase;
+                lastLifecyclePhase = phaseId.phase();
             }
         }
 
@@ -69,7 +71,7 @@ public class PhaseRecorder
         {
             return lastLifecyclePhase != null;
         }
-        return !lifecyclePhase.equals( lastLifecyclePhase );
+        return !PhaseId.of( lifecyclePhase ).phase().equals( lastLifecyclePhase );
 
     }
 
diff --git a/maven-plugin-api/src/main/mdo/lifecycle.mdo b/maven-plugin-api/src/main/mdo/lifecycle.mdo
index 7dfce74..b86fde8 100644
--- a/maven-plugin-api/src/main/mdo/lifecycle.mdo
+++ b/maven-plugin-api/src/main/mdo/lifecycle.mdo
@@ -17,8 +17,8 @@ specific language governing permissions and limitations
 under the License.
 -->
 
-<model xmlns="http://codehaus-plexus.github.io/MODELLO/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://codehaus-plexus.github.io/MODELLO/1.0.0 http://codehaus-plexus.github.io/modello/xsd/modello-1.0.0.xsd"
+<model xmlns="http://codehaus-plexus.github.io/MODELLO/1.8.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="https://codehaus-plexus.github.io/MODELLO/1.8.0 https://codehaus-plexus.github.io/modello/xsd/modello-1.8.0.xsd"
   xml.namespace="http://maven.apache.org/LIFECYCLE/${version}"
   xml.schemaLocation="http://maven.apache.org/xsd/lifecycle-${version}.xsd">
   <id>lifecycle-mappings</id>
@@ -79,13 +79,29 @@ under the License.
       <version>1.0.0</version>
       <description>A phase mapping definition.</description>
       <fields>
-        <field>
+        <field java.getter="false">
           <name>id</name>
           <required>true</required>
           <version>1.0.0</version>
           <type>String</type>
           <description>The ID of this phase, e.g., &lt;code&gt;generate-sources&lt;/code&gt;.</description>
         </field>
+        <field xml.attribute="true">
+          <name>executionPoint</name>
+          <required>false</required>
+          <version>1.0.0</version>
+          <type>String</type>
+          <defaultValue><![CDATA[]]></defaultValue>
+          <description><![CDATA[If specified, identifies this phase as a dynamic phase to decorate the specified phase id, e.g. <code>after</code> or <code>before</code>.]]></description>
+        </field>
+        <field xml.attribute="true">
+          <name>priority</name>
+          <required>false</required>
+          <version>1.0.0</version>
+          <type>int</type>
+          <defaultValue>0</defaultValue>
+          <description>If specified, identifies a within phase prioritization of executions.</description>
+        </field>
         <field>
           <name>executions</name>
           <version>1.0.0</version>
@@ -102,6 +118,46 @@ under the License.
           <description>Configuration to pass to all goals run in this phase.</description>
         </field>
       </fields>
+      <codeSegments>
+        <codeSegment>
+          <version>1.0.0</version>
+          <code><![CDATA[
+    /**
+     * Get the ID of this phase, e.g.,
+     * <code>generate-sources</code>.
+     *
+     * @return String
+     */
+    public String getRawId()
+    {
+        return id;
+    }
+
+    /**
+     * Get the effective ID of this phase, e.g.,
+     * <code>generate-sources</code> or <code>after:integration-test[1000]</code>.
+     *
+     * @return String
+     */
+    public String getId()
+    {
+        if ( executionPoint == null )
+        {
+            if ( priority == 0 )
+            {
+                return id;
+            }
+            return id + '[' + priority + ']';
+        }
+        if ( priority == 0 )
+        {
+            return executionPoint + ':' + id;
+        }
+        return executionPoint + ':' + id + '[' + priority + ']';
+    }
+]]></code>
+        </codeSegment>
+      </codeSegments>
     </class>
     <class>
       <name>Execution</name>


[maven] 04/06: [MNG-5668] Add error reporting if the user tries to invoke a dynamic phase directly

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stephenc pushed a commit to branch mng-5668-poc
in repository https://gitbox.apache.org/repos/asf/maven.git

commit b5401e6595960f7411b8d9cd7367598ce2412018
Author: Stephen Connolly <st...@gmail.com>
AuthorDate: Thu Nov 21 20:25:07 2019 +0000

    [MNG-5668] Add error reporting if the user tries to invoke a dynamic phase directly
---
 .../DefaultLifecycleTaskSegmentCalculator.java     | 48 ++++++++++++++++------
 .../internal/LifecycleTaskSegmentCalculator.java   |  2 +-
 .../maven/lifecycle/internal/MojoExecutor.java     |  3 +-
 .../apache/maven/lifecycle/internal/PhaseId.java   |  6 +--
 maven-plugin-api/src/main/mdo/lifecycle.mdo        |  2 +-
 5 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java
index cb49050..c10cbf0 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleTaskSegmentCalculator.java
@@ -86,7 +86,7 @@ public class DefaultLifecycleTaskSegmentCalculator
     public List<TaskSegment> calculateTaskSegments( MavenSession session, List<String> tasks )
         throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
         MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
-        PluginVersionResolutionException
+        PluginVersionResolutionException, LifecyclePhaseNotFoundException, LifecycleNotFoundException
     {
         List<TaskSegment> taskSegments = new ArrayList<>( tasks.size() );
 
@@ -94,24 +94,48 @@ public class DefaultLifecycleTaskSegmentCalculator
 
         for ( String task : tasks )
         {
+            PhaseId phaseId = PhaseId.of( task );
+            // if the priority is non-zero then you specified the priority on the CLI
+            if ( phaseId.priority() != 0 )
+            {
+                throw new LifecyclePhaseNotFoundException(
+                    "Dynamic phases such as \"" + task + "\" are only permitted as execution targets specified "
+                        + "inside the pom.xml. Try invoking the whole phase, i.e. \"" + phaseId.phase() + "\".", task );
+            }
             if ( isGoalSpecification( task ) )
             {
-                // "pluginPrefix:goal" or "groupId:artifactId[:version]:goal"
+                try
+                {
+                    // "pluginPrefix:goal" or "groupId:artifactId[:version]:goal"
 
-                lifecyclePluginResolver.resolveMissingPluginVersions( session.getTopLevelProject(), session );
+                    lifecyclePluginResolver.resolveMissingPluginVersions( session.getTopLevelProject(), session );
 
-                MojoDescriptor mojoDescriptor =
-                    mojoDescriptorCreator.getMojoDescriptor( task, session, session.getTopLevelProject() );
+                    MojoDescriptor mojoDescriptor =
+                        mojoDescriptorCreator.getMojoDescriptor( task, session, session.getTopLevelProject() );
 
-                boolean aggregating = mojoDescriptor.isAggregator() || !mojoDescriptor.isProjectRequired();
+                    boolean aggregating = mojoDescriptor.isAggregator() || !mojoDescriptor.isProjectRequired();
 
-                if ( currentSegment == null || currentSegment.isAggregating() != aggregating )
+                    if ( currentSegment == null || currentSegment.isAggregating() != aggregating )
+                    {
+                        currentSegment = new TaskSegment( aggregating );
+                        taskSegments.add( currentSegment );
+                    }
+
+                    currentSegment.getTasks().add( new GoalTask( task ) );
+                }
+                catch ( NoPluginFoundForPrefixException e )
                 {
-                    currentSegment = new TaskSegment( aggregating );
-                    taskSegments.add( currentSegment );
+                    if ( phaseId.executionPoint() != PhaseExecutionPoint.AS && phaseId.phase().indexOf( ':' ) == -1 )
+                    {
+                        LifecyclePhaseNotFoundException lpnfe = new LifecyclePhaseNotFoundException(
+                            "Dynamic phases such as \"" + task + "\" are only permitted as execution targets specified "
+                                + "inside the pom.xml. Try invoking the whole phase, i.e. \"" + phaseId.phase() + "\".",
+                            task );
+                        lpnfe.addSuppressed( e );
+                        throw lpnfe;
+                    }
+                    throw e;
                 }
-
-                currentSegment.getTasks().add( new GoalTask( task ) );
             }
             else
             {
@@ -152,4 +176,4 @@ public class DefaultLifecycleTaskSegmentCalculator
         return task.indexOf( ':' ) >= 0;
     }
 
-}
\ No newline at end of file
+}
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java
index 7dd84d8..7c7db5a 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleTaskSegmentCalculator.java
@@ -54,7 +54,7 @@ public interface LifecycleTaskSegmentCalculator
     List<TaskSegment> calculateTaskSegments( MavenSession session, List<String> tasks )
         throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
         MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
-        PluginVersionResolutionException;
+        PluginVersionResolutionException, LifecyclePhaseNotFoundException, LifecycleNotFoundException;
 
     boolean requiresProject( MavenSession session );
 
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
index df3f34c..ae5b03f 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
@@ -251,7 +251,8 @@ public class MojoExecutor
             {
                 pluginManager.executeMojo( session, mojoExecution );
             }
-            catch ( MojoFailureException | PluginManagerException | PluginConfigurationException | MojoExecutionException e )
+            catch ( MojoFailureException | PluginManagerException | PluginConfigurationException
+                | MojoExecutionException e )
             {
                 throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e );
             }
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
index a225541..da5bece 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/PhaseId.java
@@ -30,7 +30,7 @@ public class PhaseId
     /**
      * Interned {@link PhaseId} instances.
      */
-    private static final Map<String, PhaseId> instances = new WeakHashMap<>();
+    private static final Map<String, PhaseId> INSTANCES = new WeakHashMap<>();
 
     /**
      * The execution point of this {@link PhaseId}.
@@ -55,11 +55,11 @@ public class PhaseId
      */
     public static synchronized PhaseId of( String phase )
     {
-        PhaseId result = instances.get( phase );
+        PhaseId result = INSTANCES.get( phase );
         if ( result == null )
         {
             result = new PhaseId( phase );
-            instances.put( phase, result );
+            INSTANCES.put( phase, result );
         }
         return result;
     }
diff --git a/maven-plugin-api/src/main/mdo/lifecycle.mdo b/maven-plugin-api/src/main/mdo/lifecycle.mdo
index 8c6922f..9418758 100644
--- a/maven-plugin-api/src/main/mdo/lifecycle.mdo
+++ b/maven-plugin-api/src/main/mdo/lifecycle.mdo
@@ -137,7 +137,7 @@ under the License.
      * Get the effective ID of this phase, e.g.,
      * <code>generate-sources</code> or <code>after:integration-test[1000]</code>.
      *
-     * @return String
+     * @return the effective ID of this phase
      */
     public String getId()
     {