From ebb84860a13144f21851d910f5510bba24273108 Mon Sep 17 00:00:00 2001 From: "Andrzej J." Date: Mon, 29 Sep 2025 07:29:53 +0200 Subject: [PATCH] #979: overhaul of the updates logger; added json and csv + a new appendable xml which records multiple executions Added changeRecorder to display-property-updates, display-parent-updates, display-dependency-updates, display-extension-updates, display-plugin-updates; Added changeRecorder to display-property-updates, display-parent-updates, display-dependency-updates, display-extension-updates --- .gitignore | 1 + pom.xml | 42 ++++ versions-api/pom.xml | 13 ++ .../api/change/DependencyVersionChange.java | 2 + .../api/change/PropertyVersionChange.java | 2 + .../versions/api/recording/ChangeRecord.java | 2 + .../api/recording/ChangeRecorder.java | 2 + .../api/recording/DependencyChangeRecord.java | 2 + .../api/recording/PropertyChangeRecord.java | 2 + .../api/recording/VersionChangeRecorder.java | 59 +++++ .../VersionChangeRecorderFactory.java | 38 ++++ .../src/site/markdown/change-recorder.md.vm | 87 ++++--- versions-common/pom.xml | 23 ++ .../change/AbstractVersionChanger.java | 86 ------- .../change/CompositeVersionChanger.java | 58 ----- .../DefaultDependencyVersionChange.java | 3 + .../change/DefaultPropertyVersionChange.java | 3 +- .../change/DependencyVersionChanger.java | 65 ------ .../versions/change/ParentVersionChanger.java | 63 ------ .../versions/change/PluginVersionChanger.java | 63 ------ .../change/ProjectVersionChanger.java | 62 ----- .../mojo/versions/change/VersionChanger.java | 35 --- .../change/VersionChangerFactory.java | 212 ------------------ .../recording/ChangeRecorderNull.java | 44 ---- .../recording/ChangeRecorderRenderer.java | 31 +++ .../versions/recording/ChangeRecorderXML.java | 128 ----------- .../CsvVersionChangeRecorderFactory.java | 40 ++++ .../DefaultDependencyChangeRecord.java | 2 + .../DefaultPropertyChangeRecord.java | 2 + .../GenericVersionChangeRecorder.java | 85 +++++++ .../JsonVersionChangeRecorderFactory.java | 39 ++++ .../NoneVersionChangeRecorderFactory.java | 47 ++++ .../recording/VersionChangeFileHelper.java | 33 +++ .../XmlVersionChangeRecorderFactory.java | 54 +++++ .../csv/ChangeRecorderLogCsvDeserializer.java | 115 ++++++++++ .../csv/ChangeRecorderLogCsvModule.java | 23 ++ .../csv/ChangeRecorderLogCsvSerializer.java | 117 ++++++++++ .../csv/CsvVersionChangeRenderer.java | 92 ++++++++ .../json/JsonIncludeNonNullMixIn.java | 9 + .../json/JsonVersionChangeModule.java | 66 ++++++ .../json/JsonVersionChangeRenderer.java | 89 ++++++++ .../recording/json/VersionChangeMixin.java | 21 ++ .../xml/LegacyXmlVersionChangeRenderer.java | 78 +++++++ .../xml/XmlVersionChangeRenderer.java | 81 +++++++ .../recording/ChangeRecorderXMLTest.java | 121 ---------- .../csv/CsvVersionChangeRecorderTest.java | 137 +++++++++++ .../json/JsonVersionChangeRecorderTest.java | 148 ++++++++++++ .../xml/XmlVersionChangeRecorderTest.java | 152 +++++++++++++ .../mojo/versions/recording/expectedFile.xml | 5 - .../versions/recording/versions-changes.csv | 2 + .../versions/recording/versions-changes.json | 18 ++ .../versions/recording/versions-changes.xml | 6 + .../invoker.properties | 2 + .../pom.xml | 40 ++++ .../verify.groovy | 2 + .../invoker.properties | 2 + .../pom.xml | 40 ++++ .../verify.groovy | 12 + .../invoker.properties | 2 + .../pom.xml | 40 ++++ .../verify.groovy | 10 + .../invoker.properties | 2 + .../pom.xml | 40 ++++ .../verify.groovy | 10 + .../invoker.properties | 2 + .../pom.xml | 40 ++++ .../verify.groovy | 12 + .../invoker.properties | 3 +- .../verify.groovy | 14 +- .../invoker.properties | 2 + .../pom.xml | 59 +++++ .../verify.groovy | 17 ++ .../verify.groovy | 22 +- .../invoker.properties | 7 +- .../verify.groovy | 30 ++- .../verify.groovy | 2 +- .../verify.groovy | 2 +- .../invoker.properties | 7 +- .../verify.groovy | 41 +++- .../invoker.properties | 11 +- .../verify.groovy | 28 +++ .../invoker.properties | 6 +- .../verify.groovy | 42 ++++ .../invoker.properties | 8 +- .../verify.groovy | 38 ++++ ...AbstractVersionsDependencyUpdaterMojo.java | 146 +++++------- .../versions/AbstractVersionsDisplayMojo.java | 8 +- .../versions/AbstractVersionsUpdaterMojo.java | 175 +++++++++++---- .../versions/CompareDependenciesMojo.java | 145 ++++++------ .../DisplayDependencyUpdatesMojo.java | 62 ++++- .../versions/DisplayExtensionUpdatesMojo.java | 27 ++- .../versions/DisplayParentUpdatesMojo.java | 24 +- .../versions/DisplayPluginUpdatesMojo.java | 162 +++++++++---- .../versions/DisplayPropertyUpdatesMojo.java | 39 +++- .../mojo/versions/ForceReleasesMojo.java | 70 +++--- .../mojo/versions/LockSnapshotsMojo.java | 8 +- .../mojo/versions/ResolveRangesMojo.java | 8 +- .../org/codehaus/mojo/versions/SetMojo.java | 167 +++++++++++--- .../mojo/versions/SetPropertyMojo.java | 8 +- .../codehaus/mojo/versions/SetScmTagMojo.java | 8 +- .../mojo/versions/UnlockSnapshotsMojo.java | 46 ++-- .../mojo/versions/UpdateChildModulesMojo.java | 8 +- .../mojo/versions/UpdateParentMojo.java | 19 +- .../mojo/versions/UpdatePropertiesMojo.java | 8 +- .../versions/UpdatePropertiesMojoBase.java | 33 +-- .../mojo/versions/UpdatePropertyMojo.java | 14 +- .../mojo/versions/UseDepVersionMojo.java | 58 ++--- .../mojo/versions/UseLatestReleasesMojo.java | 8 +- .../mojo/versions/UseLatestSnapshotsMojo.java | 8 +- .../mojo/versions/UseLatestVersionsMojo.java | 8 +- .../versions/UseLatestVersionsMojoBase.java | 101 ++------- .../mojo/versions/UseNextReleasesMojo.java | 8 +- .../mojo/versions/UseNextSnapshotsMojo.java | 8 +- .../mojo/versions/UseNextVersionsMojo.java | 8 +- .../mojo/versions/UseReactorMojo.java | 29 ++- .../mojo/versions/UseReleasesMojo.java | 67 +++--- .../DependencyUpdatesLoggingHelper.java | 28 ++- .../markdown/examples/recording-changes.md | 126 ++++++++++- versions-maven-plugin/src/site/site.xml | 1 + .../DisplayDependencyUpdatesMojoTest.java | 32 ++- .../DisplayExtensionUpdatesMojoTest.java | 16 +- .../DisplayParentUpdatesMojoTest.java | 36 ++- .../mojo/versions/ForceReleasesMojoTest.java | 49 ++-- .../mojo/versions/LockSnapshotsMojoTest.java | 3 +- ...ratePatternsForIncludesAnExcludesTest.java | 51 +++-- .../codehaus/mojo/versions/SetMojoTest.java | 11 +- .../mojo/versions/UpdateParentMojoTest.java | 74 ++++-- .../versions/UpdatePropertiesMojoTest.java | 31 ++- .../UpdatePropertiesMojoTestBase.java | 8 +- .../mojo/versions/UpdatePropertyMojoTest.java | 27 ++- .../mojo/versions/UseDepVersionMojoTest.java | 88 +++++--- .../versions/UseLatestReleasesMojoTest.java | 12 +- .../versions/UseLatestVersionsMojoTest.java | 68 ++++-- .../UseLatestVersionsMojoTestBase.java | 25 ++- .../UseLatestVersionsRaceConditionTest.java | 30 ++- .../versions/UseNextReleasesMojoTest.java | 19 +- .../versions/UseNextVersionsMojoTest.java | 20 +- .../mojo/versions/UseReleasesMojoTest.java | 40 ++-- versions-model/pom.xml | 57 +++++ .../versions/model/VersionChangeBase.java | 26 +++ .../model/util/VersionChangeSelector.java | 48 ++++ .../model/xjb/ZonedDateTimeXmlAdapter.java | 29 +++ .../src/main/resources/xsd/bindings.xjb | 22 ++ .../src/main/resources/xsd/updates-3.0.xsd | 126 +++++++++++ versions-model/src/site/markdown/xsd/index.md | 6 + .../src/site/resources/xsd/updates-2.0.xsd | 94 ++++++++ versions-test/pom.xml | 9 + .../versions/utils/CloseableTempFile.java | 8 +- .../versions/utils/TestChangeRecorder.java | 98 -------- .../utils/TestVersionChangeRecorder.java | 84 +++++++ 150 files changed, 4299 insertions(+), 1896 deletions(-) create mode 100644 versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorder.java create mode 100644 versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorderFactory.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/CompositeVersionChanger.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderNull.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderRenderer.java delete mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderXML.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/CsvVersionChangeRecorderFactory.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/GenericVersionChangeRecorder.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/JsonVersionChangeRecorderFactory.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/NoneVersionChangeRecorderFactory.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/VersionChangeFileHelper.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/XmlVersionChangeRecorderFactory.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvDeserializer.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvModule.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvSerializer.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRenderer.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonIncludeNonNullMixIn.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeModule.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRenderer.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/VersionChangeMixin.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/LegacyXmlVersionChangeRenderer.java create mode 100644 versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRenderer.java delete mode 100644 versions-common/src/test/java/org/codehaus/mojo/versions/recording/ChangeRecorderXMLTest.java create mode 100644 versions-common/src/test/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRecorderTest.java create mode 100644 versions-common/src/test/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRecorderTest.java create mode 100644 versions-common/src/test/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRecorderTest.java delete mode 100644 versions-common/src/test/resources/org/codehaus/mojo/versions/recording/expectedFile.xml create mode 100644 versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.csv create mode 100644 versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.json create mode 100644 versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.xml create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/invoker.properties create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/pom.xml create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/verify.groovy create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/invoker.properties create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/pom.xml create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/verify.groovy create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/invoker.properties create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/pom.xml create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/verify.groovy create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/invoker.properties create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/pom.xml create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/verify.groovy create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/invoker.properties create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/pom.xml create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/verify.groovy create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/invoker.properties create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/pom.xml create mode 100644 versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/verify.groovy create mode 100644 versions-model/src/main/java/org/codehaus/mojo/versions/model/VersionChangeBase.java create mode 100644 versions-model/src/main/java/org/codehaus/mojo/versions/model/util/VersionChangeSelector.java create mode 100644 versions-model/src/main/java/org/codehaus/mojo/versions/model/xjb/ZonedDateTimeXmlAdapter.java create mode 100644 versions-model/src/main/resources/xsd/bindings.xjb create mode 100644 versions-model/src/main/resources/xsd/updates-3.0.xsd create mode 100644 versions-model/src/site/resources/xsd/updates-2.0.xsd delete mode 100644 versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java create mode 100644 versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestVersionChangeRecorder.java diff --git a/.gitignore b/.gitignore index 98c3aa27ba..2bfbc81bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ target .vscode .checkstyle /.factorypath +/hs_err_pid*.log diff --git a/pom.xml b/pom.xml index 7aa57155a6..dca95e1221 100644 --- a/pom.xml +++ b/pom.xml @@ -148,6 +148,17 @@ 0.75C 2025-11-24T17:49:22Z + + + 2.3.1 + 2.3.9 + 2.20.0 + 2.20.0 + 2.5.0 + 3.0 + 1.1.0 + 2.17.2 + 2.19.0 @@ -388,6 +399,37 @@ wagon-provider-api 3.5.3 + + org.glassfish.jaxb + jaxb-runtime + ${jaxbRuntime.version} + runtime + + + com.fasterxml.jackson.core + jackson-databind + ${jacksonDatabind.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jacksonDataformatXml.version} + + + javax.xml.bind + jaxb-api + ${jaxbApi.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-csv + ${jacksonDataformatCsv.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jacksonDatatypeJsr310.version} + diff --git a/versions-api/pom.xml b/versions-api/pom.xml index fb6ddd1ad8..512cd981c1 100644 --- a/versions-api/pom.xml +++ b/versions-api/pom.xml @@ -12,6 +12,19 @@ Versions API Extension API for Versions Plugin + + + org.codehaus.mojo.versions + versions-model + ${project.version} + + + org.apache.maven + maven-core + provided + + + diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java index de631d39fa..7b3a44a58e 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java @@ -22,7 +22,9 @@ * * @author Slawomir Jaranowski * @since 2.14.0 + * @deprecated use classes from {@code versions-model} */ +@Deprecated public interface DependencyVersionChange extends VersionChange { /** * Returns the groupId of the dependency diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java index 5452793434..cd32141615 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java @@ -22,7 +22,9 @@ * * @author Andrzej Jarmoniuk * @since 2.15.0 + * @deprecated use classes from {@code versions-model} */ +@Deprecated public interface PropertyVersionChange extends VersionChange { /** diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java index 3a266418e9..24c356e718 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java @@ -25,7 +25,9 @@ * @author Slawomir Jaranowski * @since 2.14.0 * @param concrete {@link VersionChange} sub-interface + * @deprecated use classes from {@code versions-model} */ +@Deprecated public interface ChangeRecord { /** * Returns the details about changed item diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecorder.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecorder.java index 3b23d0298c..e7f86a01bd 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecorder.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecorder.java @@ -25,7 +25,9 @@ * * @author Slawomir Jaranowski * @since 2.14.0 + * @deprecated use {@link VersionChangeRecorder} and {@code versions-model} */ +@Deprecated public interface ChangeRecorder { /** * Record that a dependency was updated. diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java index cab78ee020..4116d6e7e8 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java @@ -24,7 +24,9 @@ * * @author Slawomir Jaranowski * @since 2.14.0 + * @deprecated use classes from {@code versions-model} */ +@Deprecated public interface DependencyChangeRecord extends ChangeRecord { /** * Describes where version item is updated. diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/PropertyChangeRecord.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/PropertyChangeRecord.java index 56d3627a6a..a5d256cb5e 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/PropertyChangeRecord.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/PropertyChangeRecord.java @@ -24,5 +24,7 @@ * * @author Slawomir Jaranowski * @since 2.14.0 + * @deprecated use classes from {@code versions-model} */ +@Deprecated public interface PropertyChangeRecord extends ChangeRecord {} diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorder.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorder.java new file mode 100644 index 0000000000..ecd3870a03 --- /dev/null +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorder.java @@ -0,0 +1,59 @@ +package org.codehaus.mojo.versions.api.recording; + +/* + * Copyright MojoHaus and Contributors + * + * Licensed 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.IOException; +import java.nio.file.Path; + +import org.codehaus.mojo.versions.model.VersionChange; + +/** + * Interface for implement a recorder of version changes. + * + * @since 2.20.0 + */ +public interface VersionChangeRecorder { + /** + * Record that a version change + * + * @param versionChange a {@link VersionChange} object describing the change + * @since 2.20.0 + */ + void recordChange(VersionChange versionChange); + + /** + * Write the current set of changes to the given output path. + *

+ * Implementation is responsible for creating all missing directories. + *

+ * Output should not be created for empty record sets. + * + * @param outputPath The output path, can be null, provided by changeRecorderOutputFile + * plugin parameters + * @throws IOException On write and/or I/O errors + * @since 2.20.0 + */ + void writeReport(Path outputPath) throws IOException; + + /** + * Provides the default output file name + * + * @return default file name + */ + String getDefaultFileName(); +} diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorderFactory.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorderFactory.java new file mode 100644 index 0000000000..c2679fdaa8 --- /dev/null +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorderFactory.java @@ -0,0 +1,38 @@ +package org.codehaus.mojo.versions.api.recording; + +import java.util.Map; +import java.util.Properties; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.Log; + +/** + * A factory for version change recorders. + */ +public interface VersionChangeRecorderFactory { + + /** + * Creates a new {@link VersionChangeRecorder} instance. Convenience method without any changeRendererOptions. + * + * @param mavenSession {@link MavenSession} instance + * @param mojoExecution {@link MojoExecution} instance + * @param log {@link Log} instance + * @return a new {@link VersionChangeRecorder} instance + */ + default VersionChangeRecorder create(MavenSession mavenSession, MojoExecution mojoExecution, Log log) { + return create(mavenSession, mojoExecution, log, null); + } + + /** + * Creates a new {@link VersionChangeRecorder} instance. + * + * @param mavenSession {@link MavenSession} instance + * @param mojoExecution {@link MojoExecution} instance + * @param log {@link Log} instance + * @param changeRendererOptions {@link Properties} custom properties to pass to the renderer + * @return a new {@link VersionChangeRecorder} instance + */ + VersionChangeRecorder create( + MavenSession mavenSession, MojoExecution mojoExecution, Log log, Map changeRendererOptions); +} diff --git a/versions-api/src/site/markdown/change-recorder.md.vm b/versions-api/src/site/markdown/change-recorder.md.vm index 003317e9e1..040d643515 100644 --- a/versions-api/src/site/markdown/change-recorder.md.vm +++ b/versions-api/src/site/markdown/change-recorder.md.vm @@ -1,49 +1,75 @@ -title: Writing a own ChangeRecorder -author: Slawomir Jaranowski -date: 2022-11-20 +title: Providing a custom VersionsChangeRecorder +date: 2025-10-04 -Writing an own ChangeRecorder -============================ +Providing a custom VersionsChangeRecorder +========================================= -In order to create an own ChangeRecorder you must implement [ChangeRecorder](apidocs/org/codehaus/mojo/versions/api/recording/ChangeRecorder.html) interface. +A change recorder is a component responsible for outputting version changes. Currently, it is only being used for +recording changes for plugins that change the project. Out of the box, the following recorders are provided: -Write code ----------- +| Name | Description | +|------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| none | An "empty" recorder that will not output any changes | +| xml | A recorder writing to an XML file conforming to the legacy http://www.mojohaus.org/versions-maven-plugin/schema/updates/2.0 namespace, or to the http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0 namespace if `legacy=false` is provided as options | +| json | A recorder writing to a Json file | +| csv | A recorder writing to a CSV file | + +In order to create an own VersionChangeRecorder you must implement [VersionChangeRecorder](apidocs/org/codehaus/mojo/versions/api/recording/VersionsChangeRecorder.html) interface as well as a factory +implementing [VersionChangeRecorderFactory](apidocs/org/codehaus/mojo/versions/api/recording/VersionsChangeRecorderFactory.html). + +Create the recorder +------------------ + +The below class will create a factory instantiating an anonymous class implementing the interface. ```java -import java.io.IOException; import javax.inject.Named; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.codehaus.mojo.versions.api.recording.PropertyChangeRecord; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.VersionChange; @Named("my-recorder") -public class MyChangeRecorder implements ChangeRecorder { - +public class ExampleChangeRecorderFactory implements VersionChangeRecorderFactory { @Override - public final void recordChange(DependencyChangeRecord changeRecord) { - // your code here - } - - @Override - public final void recordChange(PropertyChangeRecord changeRecord) { - // your code here - } - - @Override - public final void writeReport(Path outputPath) throws IOException { - // your code here + public VersionChangeRecorder create( + MavenSession mavenSession, MojoExecution mojoExecution, Map ignored) { + return new VersionChangeRecorder() { + final List versionChanges = new ArrayList<>(); + + @Override + public void recordChange(VersionChange versionChange) { + versionChanges.add(versionChange.toString()); + } + + @Override + public void writeReport(Path outputPath) throws IOException { + Files.write(outputPath, versionChanges, StandardCharsets.UTF_8); + } + + @Override + public String getDefaultFileName() { + return "versions-changes.log"; + } + }; } } ``` -`Changerecoder` is stateful component, so you must not add `Singleton` annotation to it. +As `VersionChangeRecorder` is stateful, so you must not add the `Singleton` annotation to it. -Using extension ---------------- +Using the custom recorder +------------------------- Plugin configuration: @@ -56,7 +82,7 @@ Plugin configuration: your.group your-project - + @@ -67,7 +93,6 @@ Plugin configuration: my-recorder - \${project.build.directory}/my-versions-changes.txt diff --git a/versions-common/pom.xml b/versions-common/pom.xml index e75849c562..35dea3b0ea 100644 --- a/versions-common/pom.xml +++ b/versions-common/pom.xml @@ -87,6 +87,29 @@ maven-resolver-util provided + + + + org.glassfish.jaxb + jaxb-runtime + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + + com.fasterxml.jackson.dataformat + jackson-dataformat-csv + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + org.junit.jupiter junit-jupiter-api diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java deleted file mode 100644 index fb540bb434..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * 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 org.apache.maven.model.Model; -import org.apache.maven.plugin.logging.Log; -import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; - -/** - * Abstract base class for {@link VersionChanger} implementations. - *

- * This class provides common functionality and holds references to the Maven Model, a mutable XML stream reader for the POM file, - * and a logger for logging purposes. - *

- * @author Stephen Connolly - * @since 15-Sep-2010 15:59:46 - */ -public abstract class AbstractVersionChanger implements VersionChanger { - /** - * {@link Model} instance - */ - private final Model model; - - /** - * {@link MutableXMLStreamReader} instance - */ - private final MutableXMLStreamReader pom; - - /** - * {@link Log} instance - */ - private final Log log; - - /** - * Creates a new instance providing the model, mutable pom, and a logger. - * @param model {@link Model} instance - * @param pom {@link MutableXMLStreamReader} instance representing the parsed (mutable) pom file - * @param log {@link Log} instance for logging - */ - public AbstractVersionChanger(Model model, MutableXMLStreamReader pom, Log log) { - this.model = model; - this.pom = pom; - this.log = log; - } - - /** - * Returns the Maven Model instance - * @return {@link Model} instance - */ - protected Model getModel() { - return model; - } - - /** - * Returns the {@link MutableXMLStreamReader} instance representing the parsed and possibly modified POM file. - * @return {@link MutableXMLStreamReader} instance under changes - */ - protected MutableXMLStreamReader getPom() { - return pom; - } - - /** - * Returns the {@link Log} instance - * @return {@link Log} instance - */ - protected Log getLog() { - return log; - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/CompositeVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/CompositeVersionChanger.java deleted file mode 100644 index 64a391a85e..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/CompositeVersionChanger.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.xml.stream.XMLStreamException; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.codehaus.mojo.versions.api.change.DependencyVersionChange; - -/** - * A composite version changer, which chains version changers together and executes the chain - * in {@link #apply(DependencyVersionChange)} until an exception occurs or the chain is through. - */ -public class CompositeVersionChanger implements VersionChanger { - private final List composites; - - /** - * Construct a new composite version changed based on an array of version changers - * @param composites array of version changes to compose from - */ - public CompositeVersionChanger(VersionChanger[] composites) { - this.composites = new ArrayList<>(Arrays.asList(composites)); - } - - /** - * Construct a new composite version changed based on a {@link List} of version changers - * @param composites list of version changes to compose from - */ - public CompositeVersionChanger(List composites) { - this.composites = new ArrayList<>(composites); - } - - /** - * {@inheritDoc} - */ - @Override - public void apply(DependencyVersionChange versionChange) throws XMLStreamException { - for (VersionChanger delegate : composites) { - delegate.apply(versionChange); - } - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java index a0e12a9581..9f75d368bf 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java @@ -24,7 +24,10 @@ * * @author Stephen Connolly * @since 15-Sep-2010 14:48:10 + * + * @deprecated replaced by {@code versions-model} */ +@Deprecated public final class DefaultDependencyVersionChange implements DependencyVersionChange { private final String groupId; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java index cfe676c2eb..b6fdb81684 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java @@ -23,8 +23,9 @@ /** * Represents a change of a property value * - * @author Andrzej Jarmoniuk + * @deprecated replaced by {@code versions-model} */ +@Deprecated public final class DefaultPropertyVersionChange implements PropertyVersionChange { private final String property; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java deleted file mode 100644 index 9dfc0ef7e8..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.xml.stream.XMLStreamException; - -import org.apache.maven.model.Model; -import org.apache.maven.plugin.logging.Log; -import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.change.DependencyVersionChange; -import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; - -/** - * A {@link VersionChanger} implementation that changes dependency versions. - *

- * This class extends the {@link AbstractVersionChanger} and provides functionality to update - * dependency versions in a Maven POM file. It utilizes the {@link PomHelper} to set the new versions - * and logs the changes made. - *

- * @author Stephen Connolly - */ -public class DependencyVersionChanger extends AbstractVersionChanger { - - /** - * Constructs a new instance - * @param model {@link Model} instance - * @param pom {@link MutableXMLStreamReader} representing the pom file to be modified - * @param reporter {@link Log} object - */ - public DependencyVersionChanger(Model model, MutableXMLStreamReader pom, Log reporter) { - super(model, pom, reporter); - } - /** - * {@inheritDoc} - */ - @Override - public void apply(DependencyVersionChange versionChange) throws XMLStreamException { - if (PomHelper.setDependencyVersion( - getPom(), - versionChange.getGroupId(), - versionChange.getArtifactId(), - versionChange.getOldVersion(), - versionChange.getNewVersion(), - getModel(), - getLog())) { - getLog().info(" Updating dependency " + versionChange.getGroupId() + ":" - + versionChange.getArtifactId()); - getLog().info(" from version " + versionChange.getOldVersion() + " to " - + versionChange.getNewVersion()); - } - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java deleted file mode 100644 index ef9b436280..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.xml.stream.XMLStreamException; - -import org.apache.maven.model.Model; -import org.apache.maven.plugin.logging.Log; -import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.change.DependencyVersionChange; -import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; - -/** - * A {@link VersionChanger} implementation that changes dependency versions. - *

- * This class extends the {@link AbstractVersionChanger} and provides functionality to update - * dependency versions in a Maven POM file. It utilizes the {@link PomHelper} to - * set the new versions and logs the changes made. - *

- * @author Stephen Connolly - */ -public class ParentVersionChanger extends AbstractVersionChanger { - - /** - * Constructs a new instance - * @param model {@link Model} instance - * @param pom {@link MutableXMLStreamReader} representing the pom file to be modified - * @param reporter {@link Log} object - */ - public ParentVersionChanger(Model model, MutableXMLStreamReader pom, Log reporter) { - super(model, pom, reporter); - } - - /** - * {@inheritDoc} - */ - @Override - public void apply(DependencyVersionChange versionChange) throws XMLStreamException { - if (getModel().getParent() != null - && versionChange.getGroupId().equals(getModel().getParent().getGroupId()) - && versionChange.getArtifactId().equals(getModel().getParent().getArtifactId())) { - if (PomHelper.setProjectParentVersion(getPom(), versionChange.getNewVersion())) { - getLog().info(" Updating parent " + versionChange.getGroupId() + ":" - + versionChange.getArtifactId()); - getLog().info(" from version " + versionChange.getOldVersion() + " to " - + versionChange.getNewVersion()); - } - } - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java deleted file mode 100644 index f88b407d2f..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.xml.stream.XMLStreamException; - -import org.apache.maven.model.Model; -import org.apache.maven.plugin.logging.Log; -import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.change.DependencyVersionChange; -import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; - -/** - * A {@link VersionChanger} implementation that changes plugin versions. - *

- * This class extends the {@link AbstractVersionChanger} and provides functionality to update - * plugin versions in a Maven POM file. It utilizes the {@link PomHelper} to - * set the new versions and logs the changes made. - *

- * @author Stephen Connolly - */ -public class PluginVersionChanger extends AbstractVersionChanger { - - /** - * Constructs a new instance - * @param model {@link Model} instance - * @param pom {@link MutableXMLStreamReader} representing the pom file to be modified - * @param reporter {@link Log} object - */ - public PluginVersionChanger(Model model, MutableXMLStreamReader pom, Log reporter) { - super(model, pom, reporter); - } - - /** - * {@inheritDoc} - */ - @Override - public void apply(DependencyVersionChange versionChange) throws XMLStreamException { - if (PomHelper.setPluginVersion( - getPom(), - versionChange.getGroupId(), - versionChange.getArtifactId(), - versionChange.getOldVersion(), - versionChange.getNewVersion())) { - getLog().info(" Updating plugin " + versionChange.getGroupId() + ":" + versionChange.getArtifactId()); - getLog().info(" from version " + versionChange.getOldVersion() + " to " - + versionChange.getNewVersion()); - } - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java deleted file mode 100644 index 8b56baa9bf..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.xml.stream.XMLStreamException; - -import org.apache.maven.model.Model; -import org.apache.maven.plugin.logging.Log; -import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.change.DependencyVersionChange; -import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; - -/** - * A {@link VersionChanger} implementation that changes dependency versions. - *

- * This class extends the {@link AbstractVersionChanger} and provides functionality to update - * dependency versions in a Maven POM file. It utilizes the {@link PomHelper} to - * set the new versions and logs the changes made. - *

- * @author Stephen Connolly - */ -public class ProjectVersionChanger extends AbstractVersionChanger { - - /** - * Constructs a new instance - * @param model {@link Model} instance - * @param pom {@link MutableXMLStreamReader} representing the pom file to be modified - * @param reporter {@link Log} object - */ - public ProjectVersionChanger(Model model, MutableXMLStreamReader pom, Log reporter) { - super(model, pom, reporter); - } - - /** - * {@inheritDoc} - */ - @Override - public void apply(DependencyVersionChange versionChange) throws XMLStreamException { - if (versionChange.getGroupId().equals(PomHelper.getGroupId(getModel())) - && versionChange.getArtifactId().equals(PomHelper.getArtifactId(getModel()))) { - if (PomHelper.setProjectVersion(getPom(), versionChange.getNewVersion())) { - getLog().info(" Updating project " + versionChange.getGroupId() + ":" - + versionChange.getArtifactId()); - getLog().info(" from version " + versionChange.getOldVersion() + " to " - + versionChange.getNewVersion()); - } - } - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java deleted file mode 100644 index f0be12a621..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.xml.stream.XMLStreamException; - -import org.codehaus.mojo.versions.api.change.DependencyVersionChange; - -/** - * Describes an operation that can change the version of a dependency in a POM. - * - * @author Stephen Connolly - */ -public interface VersionChanger { - /** - * Applies the implemented change on the given dependency. - * - * @param versionChange dependency to be changed - * @throws XMLStreamException thrown if the underlying XML operation does not succeed - */ - void apply(DependencyVersionChange versionChange) throws XMLStreamException; -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java deleted file mode 100644 index 121d6d30b8..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java +++ /dev/null @@ -1,212 +0,0 @@ -package org.codehaus.mojo.versions.change; - -/* - * 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.ArrayList; -import java.util.List; - -import org.apache.maven.model.Model; -import org.apache.maven.plugin.logging.Log; -import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; - -/** - * Factory for creating {@link VersionChanger} instances. - * - *

This factory must be initialized with a Maven {@link Model}, a mutable POM reader - * {@link MutableXMLStreamReader} and a {@link Log} before creating changers.

- * - * @author Stephen Connolly - * @since 15-Sep-2010 16:05:27 - */ -public class VersionChangerFactory { - - /** - * Public no-arg constructor to provide an explicit constructor comment for Javadoc. - */ - public VersionChangerFactory() { - // no-op constructor - } - - private Model model = null; - - private MutableXMLStreamReader pom = null; - - private Log log = null; - - /** - * Returns the Maven model currently set on this factory. - * - * @return the configured {@link Model}, never {@code null} after proper initialization - */ - public synchronized Model getModel() { - return model; - } - - /** - * Sets the Maven model to be used by changers produced by this factory. - * - * @param model the {@link Model} to set; must not be {@code null} - */ - public synchronized void setModel(Model model) { - this.model = model; - } - - /** - * Returns the mutable POM XML reader currently set on this factory. - * - * @return the configured {@link MutableXMLStreamReader} - */ - public synchronized MutableXMLStreamReader getPom() { - return pom; - } - - /** - * Sets the mutable POM XML reader to be used by changers produced by this factory. - * - * @param pom the {@link MutableXMLStreamReader} to set; must not be {@code null} - */ - public synchronized void setPom(MutableXMLStreamReader pom) { - this.pom = pom; - } - - /** - * Returns the logger currently set on this factory. - * - * @return the configured {@link Log} - */ - public synchronized Log getLog() { - return log; - } - - /** - * Sets the logger to be used by changers produced by this factory. - * - * @param log the {@link Log} to set; must not be {@code null} - */ - public synchronized void setLog(Log log) { - this.log = log; - } - - private synchronized void checkState() { - if (model == null) { - throw new IllegalStateException("Model has not been specified"); - } - if (pom == null) { - throw new IllegalStateException("Pom has not been specified"); - } - if (log == null) { - throw new IllegalStateException("Log has not been specified"); - } - } - - /** - * Creates a {@link PluginVersionChanger} configured with the factory's state. - * - * @return a new {@link PluginVersionChanger} - * @throws IllegalStateException if the factory has not been fully initialized - */ - public synchronized VersionChanger newPluginVersionChanger() { - checkState(); - return new PluginVersionChanger(model, pom, log); - } - - /** - * Creates a {@link DependencyVersionChanger} configured with the factory's state. - * - * @return a new {@link DependencyVersionChanger} - * @throws IllegalStateException if the factory has not been fully initialized - */ - public synchronized VersionChanger newDependencyVersionChanger() { - checkState(); - return new DependencyVersionChanger(model, pom, log); - } - - /** - * Creates a {@link ProjectVersionChanger} configured with the factory's state. - * - * @return a new {@link ProjectVersionChanger} - * @throws IllegalStateException if the factory has not been fully initialized - */ - public synchronized VersionChanger newProjectVersionChanger() { - checkState(); - return new ProjectVersionChanger(model, pom, log); - } - - /** - * Creates a {@link ParentVersionChanger} configured with the factory's state. - * - * @return a new {@link ParentVersionChanger} - * @throws IllegalStateException if the factory has not been fully initialized - */ - public synchronized VersionChanger newParentVersionChanger() { - checkState(); - return new ParentVersionChanger(model, pom, log); - } - - /** - * Creates a composite {@link VersionChanger} that will process parent, project, dependencies and plugins - * (in that order) using the factory's state. - * - * @return a new {@link CompositeVersionChanger} - * @throws IllegalStateException if the factory has not been fully initialized - */ - public synchronized VersionChanger newVersionChanger() { - checkState(); - VersionChanger[] delegates = new VersionChanger[] { - newParentVersionChanger(), - newProjectVersionChanger(), - newDependencyVersionChanger(), - newPluginVersionChanger() - }; - return new CompositeVersionChanger(delegates); - } - - /** - * Creates a composite {@link VersionChanger} that includes only the requested processors. - * - * @param processParent if true include a {@link ParentVersionChanger} - * @param processProject if true include a {@link ProjectVersionChanger} - * @param processDependencies if true include a {@link DependencyVersionChanger} - * @param processPlugins if true include a {@link PluginVersionChanger} - * @return a new {@link CompositeVersionChanger} composed of the selected changers - * @throws IllegalStateException if the factory has not been fully initialized - */ - public synchronized VersionChanger newVersionChanger( - boolean processParent, boolean processProject, boolean processDependencies, boolean processPlugins) { - checkState(); - - List delegates = new ArrayList<>(); - - if (processParent) { - delegates.add(newParentVersionChanger()); - } - if (processProject) { - delegates.add(newProjectVersionChanger()); - } - if (processDependencies) { - delegates.add(newDependencyVersionChanger()); - } - if (processPlugins) { - delegates.add(newPluginVersionChanger()); - } - - return new CompositeVersionChanger(delegates); - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderNull.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderNull.java deleted file mode 100644 index f2c9b09281..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderNull.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.codehaus.mojo.versions.recording; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.inject.Named; - -import java.nio.file.Path; - -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.codehaus.mojo.versions.api.recording.PropertyChangeRecord; - -/** - * A recorder that ignores updates. - */ -@Named("none") -public class ChangeRecorderNull implements ChangeRecorder { - /** - * Creates a new instance - */ - public ChangeRecorderNull() {} - - @Override - public final void recordChange(PropertyChangeRecord changeRecord) {} - - @Override - public final void recordChange(DependencyChangeRecord changeRecord) {} - - @Override - public final void writeReport(final Path outputPath) {} -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderRenderer.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderRenderer.java new file mode 100644 index 0000000000..e82c2db370 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderRenderer.java @@ -0,0 +1,31 @@ +package org.codehaus.mojo.versions.recording; + +import java.io.IOException; +import java.nio.file.Path; + +import org.codehaus.mojo.versions.model.ChangeRecorderLog; + +/** + * An optional API for use with the {@link GenericVersionChangeRecorder} + * + * @since 2.20.0 + */ +public interface ChangeRecorderRenderer { + /** + * Reads the change log from the given path. + * + * @param path the path to read from + * @return the read change log + * @throws IOException if an I/O error occurs + */ + ChangeRecorderLog read(Path path) throws IOException; + + /** + * Writes the change log to the given path. + * + * @param path the path to write to + * @param log the change log to write + * @throws IOException if an I/O error occurs + */ + void write(Path path, ChangeRecorderLog log) throws IOException; +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderXML.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderXML.java deleted file mode 100644 index c01b50d097..0000000000 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/ChangeRecorderXML.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.codehaus.mojo.versions.recording; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.inject.Named; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; - -import org.codehaus.mojo.versions.api.change.DependencyVersionChange; -import org.codehaus.mojo.versions.api.change.PropertyVersionChange; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.codehaus.mojo.versions.api.recording.PropertyChangeRecord; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import static java.nio.file.StandardOpenOption.CREATE; -import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; -import static java.nio.file.StandardOpenOption.WRITE; - -/** - * A recorder of version updates. - */ -@Named("xml") -public class ChangeRecorderXML implements ChangeRecorder { - /** - * The XML namespace used for serialized changes. - */ - public static final String CHANGES_NAMESPACE = "http://www.mojohaus.org/versions-maven-plugin/schema/updates/2.0"; - - private final Document document; - private final Element root; - - /** - * Creates a new instance - */ - public ChangeRecorderXML() { - try { - final DocumentBuilderFactory documentBuilders = DocumentBuilderFactory.newInstance(); - final DocumentBuilder documentBuilder = documentBuilders.newDocumentBuilder(); - document = documentBuilder.newDocument(); - root = document.createElementNS(CHANGES_NAMESPACE, "updates"); - document.appendChild(root); - } catch (final ParserConfigurationException | DOMException e) { - throw new IllegalStateException(e); - } - } - - @Override - public final void recordChange(DependencyChangeRecord changeRecord) { - Element update; - update = this.document.createElementNS(CHANGES_NAMESPACE, "dependencyUpdate"); - update.setAttribute( - "kind", ((DependencyChangeRecord) changeRecord).getKind().getLabel()); - DependencyVersionChange change = (DependencyVersionChange) changeRecord.getVersionChange(); - update.setAttribute("groupId", change.getGroupId()); - update.setAttribute("artifactId", change.getArtifactId()); - update.setAttribute("oldVersion", change.getOldVersion()); - update.setAttribute("newVersion", change.getNewVersion()); - - this.root.appendChild(update); - } - - @Override - public final void recordChange(PropertyChangeRecord changeRecord) { - Element update; - update = this.document.createElementNS(CHANGES_NAMESPACE, "propertyUpdate"); - PropertyVersionChange change = (PropertyVersionChange) changeRecord.getVersionChange(); - update.setAttribute("property", change.getProperty()); - update.setAttribute("oldValue", change.getOldValue()); - update.setAttribute("newValue", change.getNewValue()); - - this.root.appendChild(update); - } - - @Override - public final void writeReport(final Path outputPath) throws IOException { - if (outputPath == null) { - throw new IOException("changeRecorderOutputFile not provided"); - } - - if (root.getChildNodes().getLength() == 0) { - // don't generate empty file - return; - } - - Files.createDirectories(outputPath.getParent()); - - try (OutputStream outputStream = Files.newOutputStream(outputPath, CREATE, TRUNCATE_EXISTING, WRITE)) { - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); - Transformer transformer = transformerFactory.newTransformer(); - Source source = new DOMSource(this.document); - transformer.transform(source, new StreamResult(outputStream)); - outputStream.flush(); - } catch (final TransformerException ex) { - throw new IOException(ex); - } - } -} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/CsvVersionChangeRecorderFactory.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/CsvVersionChangeRecorderFactory.java new file mode 100644 index 0000000000..d79c760bc7 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/CsvVersionChangeRecorderFactory.java @@ -0,0 +1,40 @@ +package org.codehaus.mojo.versions.recording; + +import javax.inject.Named; + +import java.util.Map; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.recording.csv.CsvVersionChangeRenderer; + +/** + * A factory for rendering version changes into a CSV file + */ +@Named("csv") +public class CsvVersionChangeRecorderFactory implements VersionChangeRecorderFactory { + /** + * Create a new instance. + */ + public CsvVersionChangeRecorderFactory() {} + + @Override + public synchronized VersionChangeRecorder create( + MavenSession mavenSession, + MojoExecution mojoExecution, + Log log, + Map changeRendererOptions) { + ObjectFactory objectFactory = new ObjectFactory(); + return new GenericVersionChangeRecorder( + "versions-changes.csv", + objectFactory, + mavenSession, + mojoExecution, + log, + new CsvVersionChangeRenderer(objectFactory)); + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java index 07f48fad85..55b4d99df4 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java @@ -28,7 +28,9 @@ * * @author Slawomir Jaranowski * @since 2.14.0 + * @deprecated replaced by {@link org.codehaus.mojo.versions.model.DependencyVersionChange} */ +@Deprecated public class DefaultDependencyChangeRecord implements DependencyChangeRecord { private final ChangeKind kind; private final DependencyVersionChange versionChange; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java index 11fabf9b37..54cf60cf2c 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java @@ -27,7 +27,9 @@ * * @author Slawomir Jaranowski * @since 2.14.0 + * @deprecated replaced by {@link org.codehaus.mojo.versions.model.PropertyVersionChange} */ +@Deprecated public class DefaultPropertyChangeRecord implements PropertyChangeRecord { private final PropertyVersionChange versionChange; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/GenericVersionChangeRecorder.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/GenericVersionChangeRecorder.java new file mode 100644 index 0000000000..d1856eeb3e --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/GenericVersionChangeRecorder.java @@ -0,0 +1,85 @@ +package org.codehaus.mojo.versions.recording; + +import java.io.IOException; +import java.nio.file.Path; +import java.time.ZonedDateTime; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.model.VersionChange; +import org.codehaus.mojo.versions.model.VersionsExecution; + +/** + * Generic implementation of the {@link VersionChangeRecorder}, using a {@link ChangeRecorderRenderer} + * to render {@link ChangeRecorderLog} objects. + */ +public class GenericVersionChangeRecorder implements VersionChangeRecorder { + private final VersionsExecution versionsExecution; + + private final ObjectFactory objectFactory = new ObjectFactory(); + + private final ChangeRecorderRenderer renderer; + + private final Log log; + + private final String defaultFileName; + + /** + * Creates a new instance of the recorder + * + * @param defaultFileName default file name for the change recorder log, used if it's not provided by the user + * @param objectFactory instance of {@link ObjectFactory}, used by {@link ChangeRecorderRenderer} instances + * during deserialization to create model objects + * @param session {@link MavenSession} instance + * @param mojoExecution {@link MojoExecution} instance + * @param renderer {@link ChangeRecorderRenderer} instance used to delegate the actual rendering + */ + public GenericVersionChangeRecorder( + String defaultFileName, + ObjectFactory objectFactory, + MavenSession session, + MojoExecution mojoExecution, + Log log, + ChangeRecorderRenderer renderer) { + this.renderer = renderer; + versionsExecution = objectFactory + .createVersionsExecution() + .withGoal(mojoExecution != null ? mojoExecution.getGoal() : null) + .withDate(ZonedDateTime.now()); + this.defaultFileName = defaultFileName; + this.log = log; + } + + @Override + public void recordChange(VersionChange versionChange) { + versionsExecution.getVersionChanges().add(versionChange); + } + + @Override + public void writeReport(Path outputPath) throws IOException { + if (outputPath == null) { + throw new IllegalArgumentException("changeRecorderOutputFile not provided"); + } + log.debug("writing change record to " + outputPath); + if (versionsExecution.getVersionChanges().isEmpty()) { + // don't generate an empty file or add an entry with no changes + return; + } + ChangeRecorderLog changeRecorderLog = renderer.read(outputPath); + if (changeRecorderLog == null) { + VersionChangeFileHelper.createFile(outputPath); + changeRecorderLog = objectFactory.createChangeRecorderLog(); + } + changeRecorderLog.getUpdates().add(versionsExecution); + renderer.write(outputPath, changeRecorderLog); + } + + @Override + public String getDefaultFileName() { + return defaultFileName; + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/JsonVersionChangeRecorderFactory.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/JsonVersionChangeRecorderFactory.java new file mode 100644 index 0000000000..16e37a492d --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/JsonVersionChangeRecorderFactory.java @@ -0,0 +1,39 @@ +package org.codehaus.mojo.versions.recording; + +import javax.inject.Named; + +import java.util.Map; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.recording.json.JsonVersionChangeRenderer; + +/** + * A {@link VersionChangeRecorderFactory} for rendering version changes into a JSON file + */ +@Named("json") +public class JsonVersionChangeRecorderFactory implements VersionChangeRecorderFactory { + /** + * Create a new instance + */ + public JsonVersionChangeRecorderFactory() {} + + @Override + public synchronized VersionChangeRecorder create( + MavenSession mavenSession, + MojoExecution mojoExecution, + Log log, + Map changeRendererOptions) { + return new GenericVersionChangeRecorder( + "versions-changes.json", + new ObjectFactory(), + mavenSession, + mojoExecution, + log, + new JsonVersionChangeRenderer()); + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/NoneVersionChangeRecorderFactory.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/NoneVersionChangeRecorderFactory.java new file mode 100644 index 0000000000..8a66f383a9 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/NoneVersionChangeRecorderFactory.java @@ -0,0 +1,47 @@ +package org.codehaus.mojo.versions.recording; + +import javax.inject.Named; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.VersionChange; + +/** + * A {@link VersionChangeRecorderFactory} that creates a no-op {@link VersionChangeRecorder}. + * This implementation does not record any changes or write any report. + * It can be used when version change recording is not desired. + */ +@Named("none") +public class NoneVersionChangeRecorderFactory implements VersionChangeRecorderFactory { + /** + * Creates a new instance + */ + public NoneVersionChangeRecorderFactory() {} + + @Override + public VersionChangeRecorder create( + MavenSession mavenSession, + MojoExecution mojoExecution, + Log log, + Map changeRendererOptions) { + return new VersionChangeRecorder() { + @Override + public void recordChange(VersionChange versionChange) {} + + @Override + public void writeReport(Path outputPath) throws IOException {} + + @Override + public String getDefaultFileName() { + return ""; + } + }; + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/VersionChangeFileHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/VersionChangeFileHelper.java new file mode 100644 index 0000000000..7891fa1e2b --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/VersionChangeFileHelper.java @@ -0,0 +1,33 @@ +package org.codehaus.mojo.versions.recording; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * Helper class for file operations related to version change recording. + * + * @since 2.20.0 + */ +public class VersionChangeFileHelper { + private VersionChangeFileHelper() { + // utility class + } + + /** + * Creates a file at the specified path, including any necessary but nonexistent parent directories. + * If the file already exists, no action is taken. + * + * @param path the path of the file to create + * @throws IOException if an I/O error occurs + */ + public static void createFile(Path path) throws IOException { + Path parent = path.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + if (Files.notExists(path)) { + Files.createFile(path); + } + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/XmlVersionChangeRecorderFactory.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/XmlVersionChangeRecorderFactory.java new file mode 100644 index 0000000000..615f076961 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/XmlVersionChangeRecorderFactory.java @@ -0,0 +1,54 @@ +package org.codehaus.mojo.versions.recording; + +import javax.inject.Named; + +import java.util.Map; +import java.util.Optional; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.recording.xml.LegacyXmlVersionChangeRenderer; +import org.codehaus.mojo.versions.recording.xml.XmlVersionChangeRenderer; + +/** + * A {@link VersionChangeRecorderFactory} for rendering the updates into the format compatible + * with the legacy {@code http://www.mojohaus.org/versions-maven-plugin/schema/updates/2.0} schema + * and the current {@code http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0} schema. + * The choice of the schema version is controlled by the {@code legacy} option: + *
    + *
  • If the {@code legacy} option is not provided or set to {@code true + * (ignoring case)}, the legacy schema is used.
  • + *
  • If the {@code legacy} option is set to {@code false} (ign + * oring case), the current schema is used.
  • + *
+ * + * @since 2.20.0 + */ +@Named("xml") +public class XmlVersionChangeRecorderFactory implements VersionChangeRecorderFactory { + /** + * Create a new instance + */ + public XmlVersionChangeRecorderFactory() {} + + @Override + public VersionChangeRecorder create( + MavenSession mavenSession, MojoExecution mojoExecution, Log log, Map options) { + ObjectFactory objectFactory = new ObjectFactory(); + ChangeRecorderRenderer renderer; + if (options == null + || "true" + .equalsIgnoreCase( + Optional.ofNullable(options.get("legacy")).orElse("true"))) { + renderer = new LegacyXmlVersionChangeRenderer(objectFactory); + } else { + renderer = new XmlVersionChangeRenderer(objectFactory); + } + return new GenericVersionChangeRecorder( + "versions-changes.xml", objectFactory, mavenSession, mojoExecution, log, renderer); + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvDeserializer.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvDeserializer.java new file mode 100644 index 0000000000..df86f8b99f --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvDeserializer.java @@ -0,0 +1,115 @@ +package org.codehaus.mojo.versions.recording.csv; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.dataformat.csv.CsvParser; +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.ExtensionVersionChange; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.model.PluginVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; +import org.codehaus.mojo.versions.model.VersionsExecution; +import org.codehaus.mojo.versions.model.xjb.ZonedDateTimeXmlAdapter; + +/** + * A CSV deserializer for {@link ChangeRecorderLog}. + * + * @since 2.20.0 + */ +public class ChangeRecorderLogCsvDeserializer extends StdDeserializer { + /** + * The object factory to use to create model instances. + */ + private final ObjectFactory objectFactory; + + /** + * Creates a new deserializer. + * + * @param objectFactory the object factory to use to create model instances + */ + public ChangeRecorderLogCsvDeserializer(ObjectFactory objectFactory) { + super(VersionsExecution.class); + this.objectFactory = objectFactory; + } + + @Override + public ChangeRecorderLog deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + CsvParser csvParser = (CsvParser) p; + ObjectCodec codec = p.getCodec(); + + ChangeRecorderLog changeRecorderLog = objectFactory.createChangeRecorderLog(); + + // We’ll read row by row + String previousExecutionId = null; + for (VersionsExecution exec = null; !csvParser.isClosed() && csvParser.nextToken() != null; ) { + JsonNode node = codec.readTree(p); + + if (node.hasNonNull("execution")) { + String executionId = node.get("execution").asText(); + if (!executionId.equals(previousExecutionId)) { + exec = objectFactory.createVersionsExecution(); + changeRecorderLog.getUpdates().add(exec); + previousExecutionId = executionId; + } + } + + assert exec != null; + if (exec.getGoal() == null && node.hasNonNull("goal")) { + exec.setGoal(node.get("goal").asText()); + } + if (exec.getDate() == null && node.hasNonNull("date")) { + exec.setDate(ZonedDateTimeXmlAdapter.parse(node.get("date").asText())); + } + + String updateClass = node.get("updateClass").asText(); + if ("dependency".equals(updateClass)) { + DependencyVersionChange dep = objectFactory.createDependencyVersionChange(); + dep.setKind(DependencyChangeKind.fromValue(node.get("kind").asText())); + dep.setGroupId(node.get("groupId").asText()); + dep.setArtifactId(node.get("artifactId").asText()); + if (node.hasNonNull("oldValue")) { + dep.setOldVersion(node.get("oldValue").asText()); + } + dep.setNewVersion(node.get("newValue").asText()); + exec.getVersionChanges().add(dep); + } else if ("extension".equals(updateClass)) { + ExtensionVersionChange ext = objectFactory.createExtensionVersionChange(); + ext.setGroupId(node.get("groupId").asText()); + ext.setArtifactId(node.get("artifactId").asText()); + if (node.hasNonNull("oldValue")) { + ext.setOldVersion(node.get("oldValue").asText()); + } + ext.setNewVersion(node.get("newValue").asText()); + exec.getVersionChanges().add(ext); + } else if ("plugin".equals(updateClass)) { + PluginVersionChange plugin = objectFactory.createPluginVersionChange(); + plugin.setGroupId(node.get("groupId").asText()); + plugin.setArtifactId(node.get("artifactId").asText()); + if (node.hasNonNull("oldValue")) { + plugin.setOldVersion(node.get("oldValue").asText()); + } + plugin.setNewVersion(node.get("newValue").asText()); + if (node.hasNonNull("minMavenVersion")) { + plugin.setMinimumMavenVersion(node.get("minMavenVersion").asText()); + } + exec.getVersionChanges().add(plugin); + } else if ("property".equals(updateClass)) { + PropertyVersionChange prop = objectFactory.createPropertyVersionChange(); + prop.setProperty(node.get("property").asText()); + prop.setOldValue(node.get("oldValue").asText()); + prop.setNewValue(node.get("newValue").asText()); + exec.getVersionChanges().add(prop); + } else { + throw new IOException("Unknown updateClass: " + updateClass); + } + } + return changeRecorderLog; + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvModule.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvModule.java new file mode 100644 index 0000000000..e83eb62f2c --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvModule.java @@ -0,0 +1,23 @@ +package org.codehaus.mojo.versions.recording.csv; + +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.model.ObjectFactory; + +/** + * A Jackson module for CSV serialization and deserialization of {@link ChangeRecorderLog}. + * It registers the appropriate serializer and deserializer. + * + * @since 2.20.0 + */ +public class ChangeRecorderLogCsvModule extends SimpleModule { + /** + * Creates a new module. + * + * @param objectFactory the object factory to use to create model instances during deserialization + */ + public ChangeRecorderLogCsvModule(ObjectFactory objectFactory) { + addSerializer(ChangeRecorderLog.class, new ChangeRecorderLogCsvSerializer()); + addDeserializer(ChangeRecorderLog.class, new ChangeRecorderLogCsvDeserializer(objectFactory)); + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvSerializer.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvSerializer.java new file mode 100644 index 0000000000..4e0f422a51 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvSerializer.java @@ -0,0 +1,117 @@ +package org.codehaus.mojo.versions.recording.csv; + +import java.io.IOException; +import java.util.UUID; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.dataformat.csv.CsvGenerator; +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.ExtensionVersionChange; +import org.codehaus.mojo.versions.model.PluginVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; +import org.codehaus.mojo.versions.model.VersionChange; +import org.codehaus.mojo.versions.model.VersionsExecution; +import org.codehaus.mojo.versions.model.xjb.ZonedDateTimeXmlAdapter; + +/** + * A CSV serializer for {@link ChangeRecorderLog}. + * + * @since 2.20.0 + */ +public class ChangeRecorderLogCsvSerializer extends JsonSerializer { + + /** + * Creates a new serializer. + */ + public ChangeRecorderLogCsvSerializer() {} + + @Override + public void serialize(ChangeRecorderLog changeRecorderLog, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + CsvGenerator csvGen = (CsvGenerator) gen; + for (VersionsExecution execution : changeRecorderLog.getUpdates()) { + String executionId = UUID.randomUUID().toString(); + for (VersionChange change : execution.getVersionChanges()) { + // Start a new row + + csvGen.writeStartObject(); + csvGen.writeStringField("execution", executionId); + csvGen.writeStringField("goal", execution.getGoal()); + csvGen.writeStringField( + "date", execution.getDate() != null ? ZonedDateTimeXmlAdapter.print(execution.getDate()) : ""); + if (change instanceof DependencyVersionChange) { + writeDependency(csvGen, (DependencyVersionChange) change); + } else if (change instanceof ExtensionVersionChange) { + writeExtension(csvGen, (ExtensionVersionChange) change); + } else if (change instanceof PropertyVersionChange) { + writeProperty(csvGen, (PropertyVersionChange) change); + } else if (change instanceof PluginVersionChange) { + writePlugin(csvGen, (PluginVersionChange) change); + } else { + throw new IOException("Unknown VersionChange subtype: " + + change.getClass().getName()); + } + csvGen.writeEndObject(); + } + } + } + + private static void writePlugin(CsvGenerator csvGen, PluginVersionChange plugin) throws IOException { + csvGen.writeStringField("updateClass", "plugin"); + csvGen.writeOmittedField("kind"); + csvGen.writeStringField("groupId", plugin.getGroupId()); + csvGen.writeStringField("artifactId", plugin.getArtifactId()); + csvGen.writeOmittedField("property"); + if (plugin.getOldVersion() != null) { + csvGen.writeStringField("oldValue", plugin.getOldVersion()); + } else { + csvGen.writeOmittedField("oldValue"); + } + csvGen.writeStringField("newValue", plugin.getNewVersion()); + csvGen.writeStringField("minMavenVersion", plugin.getMinimumMavenVersion()); + } + + private static void writeProperty(CsvGenerator csvGen, PropertyVersionChange prop) throws IOException { + csvGen.writeStringField("updateClass", "property"); + csvGen.writeOmittedField("kind"); + csvGen.writeOmittedField("groupId"); + csvGen.writeOmittedField("artifactId"); + csvGen.writeStringField("property", prop.getProperty()); + csvGen.writeStringField("oldValue", prop.getOldValue()); + csvGen.writeStringField("newValue", prop.getNewValue()); + csvGen.writeOmittedField("minMavenVersion"); + } + + private static void writeDependency(CsvGenerator csvGen, DependencyVersionChange dep) throws IOException { + csvGen.writeStringField("updateClass", "dependency"); + csvGen.writeStringField("kind", dep.getKind().value()); + csvGen.writeStringField("groupId", dep.getGroupId()); + csvGen.writeStringField("artifactId", dep.getArtifactId()); + csvGen.writeOmittedField("property"); + if (dep.getOldVersion() != null) { + csvGen.writeStringField("oldValue", dep.getOldVersion()); + } else { + csvGen.writeOmittedField("oldValue"); + } + csvGen.writeStringField("newValue", dep.getNewVersion()); + csvGen.writeOmittedField("minMavenVersion"); + } + + private static void writeExtension(CsvGenerator csvGen, ExtensionVersionChange ext) throws IOException { + csvGen.writeStringField("updateClass", "extension"); + csvGen.writeOmittedField("kind"); + csvGen.writeStringField("groupId", ext.getGroupId()); + csvGen.writeStringField("artifactId", ext.getArtifactId()); + csvGen.writeOmittedField("property"); + if (ext.getOldVersion() != null) { + csvGen.writeStringField("oldValue", ext.getOldVersion()); + } else { + csvGen.writeOmittedField("oldValue"); + } + csvGen.writeStringField("newValue", ext.getNewVersion()); + csvGen.writeOmittedField("minMavenVersion"); + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRenderer.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRenderer.java new file mode 100644 index 0000000000..e23592daab --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRenderer.java @@ -0,0 +1,92 @@ +package org.codehaus.mojo.versions.recording.csv; + +/* + * Copyright MojoHaus and Contributors + * Licensed 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.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import com.fasterxml.jackson.core.exc.StreamWriteException; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvSchema; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.recording.ChangeRecorderRenderer; + +/** + * A CSV renderer for the {@link ChangeRecorderLog} + */ +public class CsvVersionChangeRenderer implements ChangeRecorderRenderer { + + private final ObjectMapper mapper; + + private final CsvSchema schema; + + /** + * Creates a new instance of CsvVersionChangeRenderer. + * + * @param objectFactory the object factory to use to create model instances + */ + public CsvVersionChangeRenderer(ObjectFactory objectFactory) { + mapper = new CsvMapper(); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new ChangeRecorderLogCsvModule(objectFactory)); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + schema = CsvSchema.builder() + .addColumn("execution") + .addColumn("goal") + .addColumn("date") + .addColumn("updateClass") + .addColumn("kind") + .addColumn("groupId") + .addColumn("artifactId") + .addColumn("property") + .addColumn("oldValue") + .addColumn("newValue") + .addColumn("minMavenVersion") + .setColumnSeparator(';') + .disableQuoteChar() + .build() + .withHeader(); + } + + @Override + public ChangeRecorderLog read(Path path) throws IOException { + if (path == null || !Files.exists(path) || Files.size(path) == 0) { + return null; + } + return mapper.readerFor(ChangeRecorderLog.class).with(schema).readValue(path.toFile()); + } + + @Override + public void write(Path path, ChangeRecorderLog log) throws IOException { + if (path == null) { + throw new IllegalArgumentException("output path not provided"); + } + if (log == null) { + throw new IllegalArgumentException("ChangeRecorderLog is null"); + } + try { + mapper.writer(schema).writeValue(path.toFile(), log); + } catch (DatabindException | StreamWriteException e) { + throw new IOException("Failed to write ChangeRecorderLog to " + path, e); + } + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonIncludeNonNullMixIn.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonIncludeNonNullMixIn.java new file mode 100644 index 0000000000..6c904a2bfe --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonIncludeNonNullMixIn.java @@ -0,0 +1,9 @@ +package org.codehaus.mojo.versions.recording.json; + +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Mix-in to instruct Jackson to omit null-valued properties during serialization. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public abstract class JsonIncludeNonNullMixIn {} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeModule.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeModule.java new file mode 100644 index 0000000000..0c1f23f308 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeModule.java @@ -0,0 +1,66 @@ +package org.codehaus.mojo.versions.recording.json; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleDeserializers; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.module.SimpleSerializers; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.VersionChange; + +/** + * A Jackson module for JSON deserialization of {@link VersionChange}. + * It registers a deserializer that can handle the polymorphic nature of VersionChange. + * + * @since 2.20.0 + */ +public class JsonVersionChangeModule extends SimpleModule { + /** + * Creates a new module. + */ + public JsonVersionChangeModule() {} + + @Override + public void setupModule(SetupContext context) { + super.setupModule(context); + + SimpleSerializers serializers = new SimpleSerializers(); + serializers.addSerializer(DependencyChangeKind.class, new DependencyChangeKindSerializer()); + context.addSerializers(serializers); + + SimpleDeserializers deserializers = new SimpleDeserializers(); + deserializers.addDeserializer(DependencyChangeKind.class, new DependencyChangeKindDeserializer()); + context.addDeserializers(deserializers); + } + + private static final class DependencyChangeKindSerializer extends JsonSerializer { + @Override + public void serialize(DependencyChangeKind value, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + if (value == null) { + gen.writeNull(); + } else { + gen.writeString(value.value()); + } + } + } + + private static final class DependencyChangeKindDeserializer extends JsonDeserializer { + @Override + public DependencyChangeKind deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + String text = p.getValueAsString(); + try { + return DependencyChangeKind.fromValue(text); + } catch (IllegalArgumentException e) { + throw JsonMappingException.from(p, "Unknown DependencyChangeKind: " + text, e); + } + } + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRenderer.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRenderer.java new file mode 100644 index 0000000000..53dd1005ad --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRenderer.java @@ -0,0 +1,89 @@ +package org.codehaus.mojo.versions.recording.json; + +/* + * Copyright MojoHaus and Contributors + * Licensed 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.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.core.exc.StreamWriteException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.recording.ChangeRecorderRenderer; + +import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS; + +/** + * A JSON renderer for the {@link ChangeRecorderLog} + */ +public class JsonVersionChangeRenderer implements ChangeRecorderRenderer { + private final ObjectMapper mapper; + + /** + * Creates a new instance of JsonVersionChangeRenderer. + */ + public JsonVersionChangeRenderer() { + mapper = new ObjectMapper(); + // Do not serialize null-valued properties so attributes like oldVersion are omitted + // from the JSON output when they are null. Register a mix-in annotated with + // @JsonInclude(Include.NON_NULL) to avoid using deprecated or unavailable APIs. + mapper.addMixIn(Object.class, JsonIncludeNonNullMixIn.class); + // Register polymorphic mix-in for VersionChange so Jackson writes/reads + // the "updateClass" discriminator automatically. + mapper.addMixIn( + org.codehaus.mojo.versions.model.VersionChange.class, + org.codehaus.mojo.versions.recording.json.VersionChangeMixin.class); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new JsonVersionChangeModule()); + mapper.disable(WRITE_DATES_AS_TIMESTAMPS); + } + + // Local mix-in to exclude null-valued properties without touching generated models. + @JsonInclude(JsonInclude.Include.NON_NULL) + private abstract static class JsonIncludeNonNullMixIn {} + + @Override + public ChangeRecorderLog read(Path path) throws IOException { + if (path == null || !Files.exists(path) || Files.size(path) == 0) { + return null; + } + try { + return mapper.readValue(path.toFile(), new TypeReference() {}); + } catch (DatabindException | StreamReadException e) { + throw new IOException("Failed to read ChangeRecorderLog from " + path, e); + } + } + + @Override + public void write(Path path, ChangeRecorderLog log) throws IOException { + if (path == null) { + throw new IllegalArgumentException("output path not provided"); + } + if (log == null) { + throw new IllegalArgumentException("ChangeRecorderLog is null"); + } + try { + mapper.writerWithDefaultPrettyPrinter().writeValue(path.toFile(), log); + } catch (DatabindException | StreamWriteException e) { + throw new IOException("Failed to write ChangeRecorderLog to " + path, e); + } + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/VersionChangeMixin.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/VersionChangeMixin.java new file mode 100644 index 0000000000..37aadc0422 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/VersionChangeMixin.java @@ -0,0 +1,21 @@ +package org.codehaus.mojo.versions.recording.json; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.ExtensionVersionChange; +import org.codehaus.mojo.versions.model.PluginVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; + +/** + * Jackson mix-in to enable polymorphic (de)serialization of {@code VersionChange} + * using an external discriminator property named "updateClass". + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "updateClass") +@JsonSubTypes({ + @JsonSubTypes.Type(value = DependencyVersionChange.class, name = "dependency"), + @JsonSubTypes.Type(value = PropertyVersionChange.class, name = "property"), + @JsonSubTypes.Type(value = PluginVersionChange.class, name = "plugin"), + @JsonSubTypes.Type(value = ExtensionVersionChange.class, name = "extension") +}) +public abstract class VersionChangeMixin {} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/LegacyXmlVersionChangeRenderer.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/LegacyXmlVersionChangeRenderer.java new file mode 100644 index 0000000000..803645bbc9 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/LegacyXmlVersionChangeRenderer.java @@ -0,0 +1,78 @@ +package org.codehaus.mojo.versions.recording.xml; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; + +import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.model.VersionsExecution; +import org.codehaus.mojo.versions.recording.ChangeRecorderRenderer; + +/** + * {@link ChangeRecorderRenderer} which renders changes in the legacy + * {@code http://www.mojohaus.org/versions-maven-plugin/schema/updates/2.0} format. + * @since 2.20.0 + */ +public final class LegacyXmlVersionChangeRenderer implements ChangeRecorderRenderer { + + private final JAXBContext jaxbContext; + + private final ObjectFactory objectFactory; + + /** + * Creates a new instance of the renderer + * @param objectFactory {@link ObjectFactory} instance + */ + public LegacyXmlVersionChangeRenderer(ObjectFactory objectFactory) { + this.objectFactory = objectFactory; + try { + this.jaxbContext = JAXBContext.newInstance(VersionsExecution.class); + } catch (JAXBException e) { + throw new IllegalStateException("Failed to initialize JAXBContext for VersionsExecution", e); + } + } + + @Override + public ChangeRecorderLog read(Path path) throws IOException { + // Legacy format is not appendable + return null; + } + + @Override + public void write(Path path, ChangeRecorderLog changeRecorderLog) throws IOException { + VersionsExecution execution = changeRecorderLog.getUpdates().get(0); + if (execution.getVersionChanges().isEmpty()) { + // don't generate an empty file or add an entry with no changes + return; + } + + // marshall a clone without goal and date set + VersionsExecution clone = + objectFactory.createVersionsExecution().withVersionChanges(execution.getVersionChanges()); + + try { + // Marshall into a StringWriter to replace the namespace + StringWriter sw = new StringWriter(); + Marshaller marshaller = jaxbContext.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE); + marshaller.marshal(objectFactory.createUpdates(clone), sw); + + // Replace schema namespace from 3.0 to 2.0 + String xml = sw.toString() + .replace( + "http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0", + "http://www.mojohaus.org/versions-maven-plugin/schema/updates/2.0"); + + Files.write(path, xml.getBytes(StandardCharsets.UTF_8)); + } catch (JAXBException e) { + throw new IOException("Failed to write legacy XML ChangeRecorder", e); + } + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRenderer.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRenderer.java new file mode 100644 index 0000000000..6932ce7e0e --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRenderer.java @@ -0,0 +1,81 @@ +package org.codehaus.mojo.versions.recording.xml; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamSource; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.codehaus.mojo.versions.model.ChangeRecorderLog; +import org.codehaus.mojo.versions.model.ObjectFactory; +import org.codehaus.mojo.versions.recording.ChangeRecorderRenderer; + +/** + * An implementation of {@link ChangeRecorderRenderer} that reads and writes XML files using JAXB. + * This implementation is compatible with the schema defined at + * {@code http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0}. + * + * @since 2.20.0 + */ +public final class XmlVersionChangeRenderer implements ChangeRecorderRenderer { + + private static final String SCHEMA_LOCATION = + "http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0 updates-3.0.xsd"; + + private final JAXBContext jaxbContext; + + private final ObjectFactory objectFactory; + + /** + * Creates a new instance of XmlVersionChangeRenderer. + * + * @param objectFactory the object factory to use to create model instances + */ + public XmlVersionChangeRenderer(ObjectFactory objectFactory) { + this.objectFactory = objectFactory; + try { + this.jaxbContext = JAXBContext.newInstance(ChangeRecorderLog.class); + } catch (JAXBException e) { + throw new IllegalStateException("Failed to initialize JAXBContext for ChangeRecorderLog", e); + } + } + + @Override + public ChangeRecorderLog read(Path path) throws IOException { + if (path == null || !Files.exists(path) || Files.size(path) == 0) { + return null; + } + try { + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + JAXBElement root = + unmarshaller.unmarshal(new StreamSource(path.toFile()), ChangeRecorderLog.class); + return root.getValue(); + } catch (JAXBException e) { + throw new IOException("Failed to read ChangeRecorderLog from " + path, e); + } + } + + @Override + public void write(Path path, ChangeRecorderLog log) throws IOException { + if (path == null) { + throw new IllegalArgumentException("output path not provided"); + } + if (log == null) { + throw new IllegalArgumentException("ChangeRecorderLog is null"); + } + try { + Marshaller marshaller = jaxbContext.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); + marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, SCHEMA_LOCATION); + marshaller.marshal(objectFactory.createChangeRecorderLog(log), path.toFile()); + } catch (JAXBException e) { + throw new IOException("Failed to write ChangeRecorderLog to " + path, e); + } + } +} diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/recording/ChangeRecorderXMLTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/recording/ChangeRecorderXMLTest.java deleted file mode 100644 index 8b76b80ef6..0000000000 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/recording/ChangeRecorderXMLTest.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.codehaus.mojo.versions.recording; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; - -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.junit.jupiter.api.Test; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; - -class ChangeRecorderXMLTest { - private static void copyResource(final String name, final Path output) throws IOException { - try (InputStream inputStream = ChangeRecorderXMLTest.class.getResourceAsStream(name)) { - Files.copy(inputStream, output, StandardCopyOption.REPLACE_EXISTING); - } - } - - private static Document parseXML(final Path path) throws ParserConfigurationException, IOException, SAXException { - final DocumentBuilderFactory documentBuilders = DocumentBuilderFactory.newInstance(); - final DocumentBuilder documentBuilder = documentBuilders.newDocumentBuilder(); - return documentBuilder.parse(path.toFile()); - } - - @Test - void testChanges() throws Exception { - final Path path0 = Files.createTempFile("ChangeRecorderTest", ".xml"); - final Path path1 = Files.createTempDirectory("ChangeRecorderTest") - .resolve("subDirectory") - .resolve("ChangeRecorderTest.xml"); - - copyResource("expectedFile.xml", path0); - - final ChangeRecorder recorder = new ChangeRecorderXML(); - recorder.recordChange(DefaultDependencyChangeRecord.builder() - .withKind(DependencyChangeRecord.ChangeKind.DEPENDENCY) - .withGroupId("org.codehaus") - .withArtifactId("example0") - .withOldVersion("0.0.1") - .withNewVersion("0.0.2") - .build()); - - recorder.recordChange(DefaultDependencyChangeRecord.builder() - .withKind(DependencyChangeRecord.ChangeKind.DEPENDENCY_MANAGEMENT) - .withGroupId("org.codehaus") - .withArtifactId("example1") - .withOldVersion("1.0.0") - .withNewVersion("2.0.0") - .build()); - - recorder.writeReport(path1); - - final Document document0 = parseXML(path0); - final Document document1 = parseXML(path1); - - final NodeList elements0 = document0.getElementsByTagNameNS(ChangeRecorderXML.CHANGES_NAMESPACE, "updated"); - final NodeList elements1 = document1.getElementsByTagNameNS(ChangeRecorderXML.CHANGES_NAMESPACE, "updated"); - - assertEquals(elements0.getLength(), elements1.getLength(), "Correct number of updates"); - - for (int index = 0; index < elements0.getLength(); ++index) { - final Element element0 = (Element) elements0.item(index); - final Element element1 = (Element) elements1.item(index); - - assertEquals( - element0.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "artifactId"), - element1.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "artifactId")); - assertEquals( - element0.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "groupId"), - element1.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "groupId")); - assertEquals( - element0.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "oldVersion"), - element1.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "oldVersion")); - assertEquals( - element0.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "newVersion"), - element1.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "newVersion")); - - // FIXME - looks like assertions not working - assertEquals( - element0.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "kind"), - element1.getAttributeNS(ChangeRecorderXML.CHANGES_NAMESPACE, "kind")); - } - } - - @Test - void emptyResultShouldNotGenerateReports() throws Exception { - Path path = Files.createTempDirectory("ChangeRecorderTest").resolve("ChangeRecorderTest.xml"); - - ChangeRecorder recorder = new ChangeRecorderXML(); - recorder.writeReport(path); - - assertFalse(Files.isRegularFile(path), "File should not be created"); - } -} diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRecorderTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRecorderTest.java new file mode 100644 index 0000000000..60829ab29e --- /dev/null +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRecorderTest.java @@ -0,0 +1,137 @@ +package org.codehaus.mojo.versions.recording.csv; + +/* + * Copyright MojoHaus and Contributors + * Licensed 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.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.recording.CsvVersionChangeRecorderFactory; +import org.codehaus.mojo.versions.utils.CloseableTempFile; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.codehaus.mojo.versions.utils.TestUtils.createTempDir; +import static org.codehaus.mojo.versions.utils.TestUtils.tearDownTempDir; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.matchesPattern; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +class CsvVersionChangeRecorderTest { + + private VersionChangeRecorder recorder; + + @BeforeEach + public void setup() { + MojoExecution mojoExecution = mock(MojoExecution.class); + doReturn("test").when(mojoExecution).getGoal(); + recorder = new CsvVersionChangeRecorderFactory().create(null, mojoExecution, new SystemStreamLog()); + } + + private void createChanges() { + recorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("org.codehaus") + .withArtifactId("example0") + .withOldVersion("0.0.1") + .withNewVersion("0.0.2")); + + recorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE) + .withGroupId("org.codehaus") + .withArtifactId("example1") + .withNewVersion("2.0.0")); + } + + @Test + void testCreateFileAndSubdirectories() throws Exception { + Path tempDir = createTempDir("testCreateFileAndSubdirectories"); + try { + createChanges(); + Path reportPath = tempDir.resolve("dir1").resolve("dir2").resolve("versions-changes.csv"); + recorder.writeReport(reportPath); + + List output = Files.readAllLines(reportPath); + assertThat( + output, + allOf( + hasItem( + matchesPattern( + "[^;]+;test;[^;]+;dependency;dependency-update;org.codehaus;example0;;0.0.1;0.0.2;")), + hasItem( + matchesPattern( + "[^;]+;test;[^;]+;dependency;dependency-management-update;org.codehaus;example1;;;2.0.0;")))); + } finally { + tearDownTempDir(tempDir); + } + } + + @Test + void testEmptyFile() throws Exception { + try (CloseableTempFile tempFile = new CloseableTempFile("ChangeRecorderTest")) { + createChanges(); + recorder.writeReport(tempFile.getPath()); + + List output = Files.readAllLines(tempFile.getPath()); + assertThat( + output, + allOf( + hasItem( + matchesPattern( + "[^;]+;test;[^;]+;dependency;dependency-update;org.codehaus;example0;;0.0.1;0.0.2;")), + hasItem( + matchesPattern( + "[^;]+;test;[^;]+;dependency;dependency-management-update;org.codehaus;example1;;;2.0.0;")))); + } + } + + @Test + void testAppend() throws Exception { + Path testFile = Paths.get("target/test-classes/org/codehaus/mojo/versions/recording/versions-changes.csv"); + createChanges(); + recorder.writeReport(testFile); + + List output = Files.readAllLines(testFile); + assertThat( + output, + allOf( + hasItem( + matchesPattern( + "[^;]+;test;[^;]+;dependency;dependency-update;org.codehaus;example0;;0.0.1-SNAPSHOT;0.0.1;")), + hasItem(matchesPattern( + "[^;]+;test;[^;]+;dependency;dependency-update;org.codehaus;example0;;0.0.1;0.0.2;")), + hasItem( + matchesPattern( + "[^;]+;test;[^;]+;dependency;dependency-management-update;org.codehaus;example1;;;2.0.0;")))); + } + + @Test + void emptyResultShouldNotGenerateReports() throws Exception { + Path path = Files.createTempDirectory("ChangeRecorderTest").resolve("ChangeRecorderTest.xml"); + recorder.writeReport(path); + assertFalse(Files.isRegularFile(path), "File should not be created"); + } +} diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRecorderTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRecorderTest.java new file mode 100644 index 0000000000..3cb33795f1 --- /dev/null +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRecorderTest.java @@ -0,0 +1,148 @@ +package org.codehaus.mojo.versions.recording.json; + +/* + * Copyright MojoHaus and Contributors + * Licensed 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.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.recording.JsonVersionChangeRecorderFactory; +import org.codehaus.mojo.versions.utils.CloseableTempFile; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.codehaus.mojo.versions.utils.TestUtils.createTempDir; +import static org.codehaus.mojo.versions.utils.TestUtils.tearDownTempDir; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +class JsonVersionChangeRecorderTest { + + private VersionChangeRecorder recorder; + + @BeforeEach + public void setup() { + MojoExecution mojoExecution = mock(MojoExecution.class); + doReturn("test").when(mojoExecution).getGoal(); + recorder = new JsonVersionChangeRecorderFactory().create(null, mojoExecution, new SystemStreamLog()); + } + + @Test + void testCreateFileAndSubdirectories() throws Exception { + Path tempDir = createTempDir("testCreateFileAndSubdirectories"); + try { + createChanges(); + Path reportPath = tempDir.resolve("dir1").resolve("dir2").resolve("report.json"); + recorder.writeReport(reportPath); + + String output = String.join("", Files.readAllLines(reportPath)).replaceAll("\\s+", ""); + assertThat( + output, + containsString( + "{\"updateClass\":\"dependency\",\"kind\":\"dependency-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example0\",\"oldVersion\":\"0.0.1\",\"newVersion\":\"0.0.2\"}")); + assertThat( + output, + containsString( + "{\"updateClass\":\"dependency\",\"kind\":\"dependency-management-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example1\",\"newVersion\":\"2.0.0\"}")); + assertThat(output, containsString("\"date\":")); + } finally { + tearDownTempDir(tempDir); + } + } + + @Test + void testEmptyFile() throws Exception { + try (CloseableTempFile tempFile = new CloseableTempFile("ChangeRecorderTest")) { + createChanges(); + recorder.writeReport(tempFile.getPath()); + + String output = + String.join("", Files.readAllLines(tempFile.getPath())).replaceAll("\\s+", ""); + assertThat( + output, + containsString( + "{\"updateClass\":\"dependency\",\"kind\":\"dependency-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example0\",\"oldVersion\":\"0.0.1\",\"newVersion\":\"0.0.2\"}")); + assertThat( + output, + containsString( + "{\"updateClass\":\"dependency\",\"kind\":\"dependency-management-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example1\",\"newVersion\":\"2.0.0\"}")); + } + } + + private void createChanges() { + recorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("org.codehaus") + .withArtifactId("example0") + .withOldVersion("0.0.1") + .withNewVersion("0.0.2")); + + recorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE) + .withGroupId("org.codehaus") + .withArtifactId("example1") + .withNewVersion("2.0.0")); + } + + @Test + void testAppend() throws Exception { + Path tempDir = createTempDir("testAppend"); + try { + Path testFile = tempDir.resolve("versions-changes.json"); + Files.copy( + Paths.get("src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.json"), + testFile); + createChanges(); + recorder.writeReport(testFile); + + String output = String.join("", Files.readAllLines(testFile)).replaceAll("\\s+", ""); + assertThat( + output, + containsString( + "{\"versionChanges\":[{\"updateClass\":\"dependency\",\"kind\":\"dependency-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example0\",\"oldVersion\":\"0.0.1-SNAPSHOT\",\"newVersion\":\"0.0.1\"}],\"goal\":\"test\",\"date\":\"2025-10-03T05:05:38.437013556Z\"}")); + assertThat( + output, + containsString( + "{\"updateClass\":\"dependency\",\"kind\":\"dependency-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example0\",\"oldVersion\":\"0.0.1-SNAPSHOT\",\"newVersion\":\"0.0.1\"}")); + assertThat( + output, + containsString( + "{\"updateClass\":\"dependency\",\"kind\":\"dependency-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example0\",\"oldVersion\":\"0.0.1\",\"newVersion\":\"0.0.2\"}")); + assertThat( + output, + containsString( + "{\"updateClass\":\"dependency\",\"kind\":\"dependency-management-update\",\"groupId\":\"org.codehaus\",\"artifactId\":\"example1\",\"newVersion\":\"2.0.0\"}")); + assertThat(output, containsString("\"date\":")); + } finally { + tearDownTempDir(tempDir); + } + } + + @Test + void emptyResultShouldNotGenerateReports() throws Exception { + Path path = Files.createTempDirectory("ChangeRecorderTest").resolve("ChangeRecorderTest.xml"); + recorder.writeReport(path); + assertFalse(Files.isRegularFile(path), "File should not be created"); + } +} diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRecorderTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRecorderTest.java new file mode 100644 index 0000000000..cb358c6d89 --- /dev/null +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/recording/xml/XmlVersionChangeRecorderTest.java @@ -0,0 +1,152 @@ +package org.codehaus.mojo.versions.recording.xml; + +/* + * Copyright MojoHaus and Contributors + * Licensed 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.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; + +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.recording.XmlVersionChangeRecorderFactory; +import org.codehaus.mojo.versions.utils.CloseableTempFile; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.codehaus.mojo.versions.utils.TestUtils.createTempDir; +import static org.codehaus.mojo.versions.utils.TestUtils.tearDownTempDir; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +class XmlVersionChangeRecorderTest { + + private VersionChangeRecorder recorder; + + @BeforeEach + public void setup() { + MojoExecution mojoExecution = mock(MojoExecution.class); + doReturn("test").when(mojoExecution).getGoal(); + recorder = new XmlVersionChangeRecorderFactory() + .create(null, mojoExecution, new SystemStreamLog(), Collections.singletonMap("legacy", "false")); + } + + @Test + void testCreateFileAndSubdirectories() throws Exception { + Path tempDir = createTempDir("testCreateFileAndSubdirectories"); + try { + createChanges(); + Path reportPath = tempDir.resolve("dir1").resolve("dir2").resolve("report.xml"); + recorder.writeReport(reportPath); + + String output = String.join("", Files.readAllLines(reportPath)); + assertThat( + output, + containsString( + "changeRecorderLog xmlns=\"http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0\"")); + assertThat(output, containsString("")); + assertThat( + output, + containsString( + "")); + } finally { + tearDownTempDir(tempDir); + } + } + + @Test + void testEmptyFile() throws Exception { + try (CloseableTempFile tempFile = new CloseableTempFile("ChangeRecorderTest")) { + createChanges(); + recorder.writeReport(tempFile.getPath()); + + String output = String.join("", Files.readAllLines(tempFile.getPath())); + assertThat( + output, + containsString( + "changeRecorderLog xmlns=\"http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0\"")); + assertThat(output, containsString("")); + assertThat( + output, + containsString( + "")); + } + } + + private void createChanges() { + recorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("org.codehaus") + .withArtifactId("example0") + .withOldVersion("0.0.1") + .withNewVersion("0.0.2")); + + recorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE) + .withGroupId("org.codehaus") + .withArtifactId("example1") + .withNewVersion("2.0.0")); + } + + @Test + void testAppend() throws Exception { + Path testFile = Paths.get("target/test-classes/org/codehaus/mojo/versions/recording/versions-changes.xml"); + createChanges(); + recorder.writeReport(testFile); + + String output = String.join("", Files.readAllLines(testFile)); + assertThat( + output, + containsString( + "changeRecorderLog xmlns=\"http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0\"")); + assertThat(output, containsString("")); + + assertThat(output, containsString("")); + assertThat( + output, + containsString( + "")); + } + + @Test + void emptyResultShouldNotGenerateReports() throws Exception { + Path path = Files.createTempDirectory("ChangeRecorderTest").resolve("ChangeRecorderTest.xml"); + recorder.writeReport(path); + assertFalse(Files.isRegularFile(path), "File should not be created"); + } +} diff --git a/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/expectedFile.xml b/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/expectedFile.xml deleted file mode 100644 index 0522410e05..0000000000 --- a/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/expectedFile.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.csv b/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.csv new file mode 100644 index 0000000000..28c230444e --- /dev/null +++ b/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.csv @@ -0,0 +1,2 @@ +execution;goal;date;updateClass;kind;groupId;artifactId;property;oldValue;newValue;minMavenVersion +c0cbf50d-047a-483a-8046-6e5631f94365;test;2025-10-04T11:10:51.765+02:00;dependency;dependency-update;org.codehaus;example0;;0.0.1-SNAPSHOT;0.0.1; diff --git a/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.json b/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.json new file mode 100644 index 0000000000..2365176707 --- /dev/null +++ b/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.json @@ -0,0 +1,18 @@ +{ + "updates": [ + { + "versionChanges": [ + { + "updateClass": "dependency", + "kind": "dependency-update", + "groupId": "org.codehaus", + "artifactId": "example0", + "oldVersion": "0.0.1-SNAPSHOT", + "newVersion": "0.0.1" + } + ], + "goal": "test", + "date": "2025-10-03T07:05:38.437013556+02:00" + } + ] +} diff --git a/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.xml b/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.xml new file mode 100644 index 0000000000..e80f776712 --- /dev/null +++ b/versions-common/src/test/resources/org/codehaus/mojo/versions/recording/versions-changes.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/invoker.properties b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/invoker.properties new file mode 100644 index 0000000000..f426f4f222 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:update-parent +invoker.mavenOpts=-DchangeRecorderFormat=csv diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/pom.xml b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/pom.xml new file mode 100644 index 0000000000..10de782fb5 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + + localhost + dummy-parent + 1.0 + + + localhost + it-201 + 1.0 + pom + update-parent basic test + + + + + + maven-clean-plugin + 2.2 + + + maven-deploy-plugin + 2.3 + + + maven-install-plugin + 2.2 + + + maven-site-plugin + 2.0 + + + + + + diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/verify.groovy new file mode 100644 index 0000000000..abc9c140c9 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-csv/verify.groovy @@ -0,0 +1,2 @@ +def csvChanges = new File(basedir, 'target/versions-changes.csv').text +assert csvChanges =~ "[^;]+;update-parent;[^;]+;dependency;parent-update;localhost;dummy-parent;;1.0;3.0;" diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/invoker.properties b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/invoker.properties new file mode 100644 index 0000000000..64804afd89 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:update-parent +invoker.mavenOpts=-DchangeRecorderFormat=json diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/pom.xml b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/pom.xml new file mode 100644 index 0000000000..10de782fb5 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + + localhost + dummy-parent + 1.0 + + + localhost + it-201 + 1.0 + pom + update-parent basic test + + + + + + maven-clean-plugin + 2.2 + + + maven-deploy-plugin + 2.3 + + + maven-install-plugin + 2.2 + + + maven-site-plugin + 2.0 + + + + + + diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/verify.groovy new file mode 100644 index 0000000000..06c9ede236 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-json/verify.groovy @@ -0,0 +1,12 @@ +import groovy.json.JsonSlurper + +def jsonChanges = new JsonSlurper().parse(new File(basedir, 'target/versions-changes.json')) +assert jsonChanges.updates[0].goal == "update-parent" +assert jsonChanges.updates[0].versionChanges.any {node -> + node.updateClass == 'dependency' + && node.kind == 'parent-update' + && node.groupId == 'localhost' + && node.artifactId == 'dummy-parent' + && node.oldVersion == '1.0' + && node.newVersion == '3.0' +} diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/invoker.properties b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/invoker.properties new file mode 100644 index 0000000000..d40e892bcb --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:update-parent +invoker.mavenOpts=-DchangeRecorderFormat=xml -DchangeRecorderOutputFile=target/change-recorder.xml diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/pom.xml b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/pom.xml new file mode 100644 index 0000000000..10de782fb5 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + + localhost + dummy-parent + 1.0 + + + localhost + it-201 + 1.0 + pom + update-parent basic test + + + + + + maven-clean-plugin + 2.2 + + + maven-deploy-plugin + 2.3 + + + maven-install-plugin + 2.2 + + + maven-site-plugin + 2.0 + + + + + + diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/verify.groovy new file mode 100644 index 0000000000..8d91ad0ea4 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFile/verify.groovy @@ -0,0 +1,10 @@ +import groovy.xml.XmlSlurper + +def xmlChanges = new XmlSlurper().parse(new File(basedir, 'target/change-recorder.xml')) +assert xmlChanges.dependencyUpdate.any {node -> + node.@kind == 'parent-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-parent' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/invoker.properties b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/invoker.properties new file mode 100644 index 0000000000..18678265e0 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:update-parent +invoker.mavenOpts=-DchangeRecorderFormat=xml -DchangeRecorderOutputFileName=change-recorder.xml diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/pom.xml b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/pom.xml new file mode 100644 index 0000000000..10de782fb5 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + + localhost + dummy-parent + 1.0 + + + localhost + it-201 + 1.0 + pom + update-parent basic test + + + + + + maven-clean-plugin + 2.2 + + + maven-deploy-plugin + 2.3 + + + maven-install-plugin + 2.2 + + + maven-site-plugin + 2.0 + + + + + + diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/verify.groovy new file mode 100644 index 0000000000..fa831b6ef4 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-outputFileName/verify.groovy @@ -0,0 +1,10 @@ +import groovy.xml.XmlSlurper + +def xmlChanges = new XmlSlurper().parse(new File(basedir, 'target/change-recorder.xml')) +assert xmlChanges.dependencyUpdate.any {node -> + node.@kind == 'parent-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-parent' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} \ No newline at end of file diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/invoker.properties b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/invoker.properties new file mode 100644 index 0000000000..1ae4ebb6dc --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:update-parent +invoker.mavenOpts=-DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/pom.xml b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/pom.xml new file mode 100644 index 0000000000..10de782fb5 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + + + localhost + dummy-parent + 1.0 + + + localhost + it-201 + 1.0 + pom + update-parent basic test + + + + + + maven-clean-plugin + 2.2 + + + maven-deploy-plugin + 2.3 + + + maven-install-plugin + 2.2 + + + maven-site-plugin + 2.0 + + + + + + diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/verify.groovy new file mode 100644 index 0000000000..ac8001fb3e --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001-xml3/verify.groovy @@ -0,0 +1,12 @@ +import groovy.xml.XmlSlurper + +def changeRecorderLog = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changeRecorderLog.updates.@goal == "update-parent" +assert !changeRecorderLog.updates.@date.isEmpty() +assert changeRecorderLog.updates.dependencyUpdate.any {node -> + node.@kind == 'parent-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-parent' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001/invoker.properties b/versions-maven-plugin/src/it/it-changerecord-update-parent-001/invoker.properties index 5ab6491f40..058e7f3e0e 100644 --- a/versions-maven-plugin/src/it/it-changerecord-update-parent-001/invoker.properties +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001/invoker.properties @@ -1 +1,2 @@ -invoker.goals=-DchangeRecorderFormat=xml ${project.groupId}:${project.artifactId}:${project.version}:update-parent +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:update-parent +invoker.mavenOpts=-DchangeRecorderFormat=xml diff --git a/versions-maven-plugin/src/it/it-changerecord-update-parent-001/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-parent-001/verify.groovy index 986173c15a..ce09b6f22f 100644 --- a/versions-maven-plugin/src/it/it-changerecord-update-parent-001/verify.groovy +++ b/versions-maven-plugin/src/it/it-changerecord-update-parent-001/verify.groovy @@ -1,8 +1,10 @@ import groovy.xml.XmlSlurper -def changes = new XmlSlurper().parse( new File( basedir, 'target/versions-changes.xml' ) ) -assert !(changes.dependencyUpdate.find { node -> node.@kind == 'parent-update' - && node.@groupId == 'localhost' - && node.@artifactId == 'dummy-parent' - && node.@oldVersion == '1.0' - && node.@newVersion == '3.0' }.isEmpty()) +def xmlChanges = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert xmlChanges.dependencyUpdate.any {node -> + node.@kind == 'parent-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-parent' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} diff --git a/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/invoker.properties b/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/invoker.properties new file mode 100644 index 0000000000..b301ae63b2 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:update-properties +invoker.mavenOpts=-DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false \ No newline at end of file diff --git a/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/pom.xml b/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/pom.xml new file mode 100644 index 0000000000..21aa2d7b84 --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/pom.xml @@ -0,0 +1,59 @@ + + 4.0.0 + + localhost + it-001 + 1.0 + pom + update-properties with one property only + + + 1.0 + + + + + + + maven-clean-plugin + 2.2 + + + maven-deploy-plugin + 2.3 + + + maven-install-plugin + 2.2 + + + maven-site-plugin + 2.0 + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + api + + + localhost + dummy-api + + + + + + + + + + diff --git a/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/verify.groovy new file mode 100644 index 0000000000..5438cbdb8f --- /dev/null +++ b/versions-maven-plugin/src/it/it-changerecord-update-properties-001-xml3/verify.groovy @@ -0,0 +1,17 @@ +import groovy.xml.XmlSlurper + +def changeRecorderLog = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changeRecorderLog.updates.@goal == "update-properties" +assert !changeRecorderLog.updates.@date.isEmpty() +assert changeRecorderLog.updates.dependencyUpdate.any {node -> + node.@kind == 'property-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-api' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} +assert changeRecorderLog.updates.propertyUpdate.any {node -> + node.@property == 'api' + && node.@oldValue == '1.0' + && node.@newValue == '3.0' +} diff --git a/versions-maven-plugin/src/it/it-changerecord-update-properties-001/verify.groovy b/versions-maven-plugin/src/it/it-changerecord-update-properties-001/verify.groovy index d1734b1ca2..f1484aa644 100644 --- a/versions-maven-plugin/src/it/it-changerecord-update-properties-001/verify.groovy +++ b/versions-maven-plugin/src/it/it-changerecord-update-properties-001/verify.groovy @@ -1,11 +1,15 @@ import groovy.xml.XmlSlurper -def changes = new XmlSlurper().parse( new File( basedir, 'target/versions-changes.xml' ) ) -assert !(changes.dependencyUpdate.find { node -> node.@kind == 'property-update' - && node.@groupId == 'localhost' - && node.@artifactId == 'dummy-api' - && node.@oldVersion == '1.0' - && node.@newVersion == '3.0' }.isEmpty()) -assert !(changes.propertyUpdate.find { node -> node.@property == 'api' - && node.@oldValue == '1.0' - && node.@newValue == '3.0' }.isEmpty()) +def changes = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changes.dependencyUpdate.any {node -> + node.@kind == 'property-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-api' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} +assert changes.propertyUpdate.any {node -> + node.@property == 'api' + && node.@oldValue == '1.0' + && node.@newValue == '3.0' +} diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-001/invoker.properties b/versions-maven-plugin/src/it/it-display-dependency-updates-001/invoker.properties index fad6299506..2498b97be2 100644 --- a/versions-maven-plugin/src/it/it-display-dependency-updates-001/invoker.properties +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-001/invoker.properties @@ -1,5 +1,8 @@ invoker.goals.1 = ${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates -invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 +invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false invoker.goals.2 = ${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates -invoker.mavenOpts.2 = -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -Dmaven.version.ignore=3.0 +invoker.mavenOpts.2 = -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -Dmaven.version.ignore=3.0 -DchangeRecorderFormat=json + +invoker.goals.3 = ${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates +invoker.mavenOpts.3 = -DchangeRecorderFormat=csv diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-001/verify.groovy b/versions-maven-plugin/src/it/it-display-dependency-updates-001/verify.groovy index eee26c892b..2d3e2d9b94 100644 --- a/versions-maven-plugin/src/it/it-display-dependency-updates-001/verify.groovy +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-001/verify.groovy @@ -1,6 +1,34 @@ +import groovy.xml.XmlSlurper +import groovy.json.JsonSlurper + output = new File(basedir, "output1.txt").text assert output =~ /\Qlocalhost:dummy-api\E\s*\.*\s*1\.1\s+->\s+3\.0\b/ output = new File(basedir, "output2.txt").text -assert ! ( output =~ /\Qlocalhost:dummy-api\E\s*\.*\s*1\.1\s+->\s+3\.0\b/ ) +assert !(output =~ /\Qlocalhost:dummy-api\E\s*\.*\s*1\.1\s+->\s+3\.0\b/) assert output =~ /\Qlocalhost:dummy-api\E\s*\.*\s*1\.1\s+->\s+2\.1\b/ + +def changeRecorderLog = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changeRecorderLog.updates.@goal == "display-dependency-updates" +assert !changeRecorderLog.updates.@date.isEmpty() +assert changeRecorderLog.updates.dependencyUpdate.any {node -> + node.@kind == 'dependency-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-api' + && node.@oldVersion == '1.1' + && node.@newVersion == '3.0' +} + +def jsonChanges = new JsonSlurper().parse(new File(basedir, 'target/versions-changes.json')) +assert jsonChanges.updates[0].goal == "display-dependency-updates" +assert jsonChanges.updates[0].versionChanges.any {node -> + node.updateClass == 'dependency' + && node.kind == 'dependency-update' + && node.groupId == 'localhost' + && node.artifactId == 'dummy-api' + && node.oldVersion == '1.1' + && node.newVersion == '2.1' +} + +def csvChanges = new File(basedir, 'target/versions-changes.csv').text +assert csvChanges =~ "[^;]+;display-dependency-updates;[^;]+;dependency;dependency-update;localhost;dummy-api;;1\\.1;3\\.0;" diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-1/verify.groovy b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-1/verify.groovy index 4324fba3cc..bfa744bf27 100644 --- a/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-1/verify.groovy +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-1/verify.groovy @@ -7,7 +7,7 @@ assert buildLog.text.contains( '[INFO] localhost:dummy-api ................... assert buildLog.text.contains( '[INFO] The following dependencies in Dependencies have newer versions:' ) assert buildLog.text.contains( '[INFO] localhost:dummy-api ....................................... 2.0 -> 3.0' ) -assert buildLog.text.contains( '[INFO] The following dependencies in pluginManagement of plugins have newer versions:' ) +assert buildLog.text.contains( '[INFO] The following dependencies in Plugin Management Dependencies have newer versions:' ) assert buildLog.text.contains( '[INFO] localhost:dummy-api ....................................... 1.2 -> 3.0' ) assert buildLog.text.contains( '[INFO] The following dependencies in Plugin Dependencies have newer versions:') diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-2/verify.groovy b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-2/verify.groovy index 536e943313..959200ec0e 100644 --- a/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-2/verify.groovy +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-34-2/verify.groovy @@ -7,7 +7,7 @@ assert buildLog.text.contains( '[INFO] localhost:dummy-api ................... assert buildLog.text.contains( '[INFO] The following dependencies in Dependencies have newer versions:' ) assert buildLog.text.contains( '[INFO] localhost:dummy-api ....................................... 2.0 -> 3.0' ) -assert buildLog.text.contains( '[INFO] The following dependencies in pluginManagement of plugins have newer versions:' ) +assert buildLog.text.contains( '[INFO] The following dependencies in Plugin Management Dependencies have newer versions:' ) assert buildLog.text.contains( '[INFO] localhost:dummy-api ....................................... 1.2 -> 3.0' ) assert !buildLog.text.contains( '[INFO] The following dependencies in Plugin Dependencies have newer versions:') diff --git a/versions-maven-plugin/src/it/it-display-extension-updates-001/invoker.properties b/versions-maven-plugin/src/it/it-display-extension-updates-001/invoker.properties index 5da846218c..38e5483eca 100644 --- a/versions-maven-plugin/src/it/it-display-extension-updates-001/invoker.properties +++ b/versions-maven-plugin/src/it/it-display-extension-updates-001/invoker.properties @@ -1,8 +1,11 @@ invoker.goals.1 = ${project.groupId}:${project.artifactId}:${project.version}:display-extension-updates -invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 +invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false invoker.goals.2 = ${project.groupId}:${project.artifactId}:${project.version}:display-extension-updates invoker.mavenOpts.2 = -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -DextensionExcludes=localhost invoker.goals.3 = ${project.groupId}:${project.artifactId}:${project.version}:display-extension-updates -invoker.mavenOpts.3 = -Dversions.outputFile=./output3.txt -DoutputEncoding=UTF-8 -DextensionIncludes=localhost -DextensionExcludes=localhost:dummy-api +invoker.mavenOpts.3 = -Dversions.outputFile=./output3.txt -DoutputEncoding=UTF-8 -DextensionIncludes=localhost -DextensionExcludes=localhost:dummy-api -DchangeRecorderFormat=json + +invoker.goals.4 = ${project.groupId}:${project.artifactId}:${project.version}:display-extension-updates +invoker.mavenOpts.4 = -Dversions.outputFile=./output4.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=csv diff --git a/versions-maven-plugin/src/it/it-display-extension-updates-001/verify.groovy b/versions-maven-plugin/src/it/it-display-extension-updates-001/verify.groovy index 4f5fe3ab69..aa2507f073 100644 --- a/versions-maven-plugin/src/it/it-display-extension-updates-001/verify.groovy +++ b/versions-maven-plugin/src/it/it-display-extension-updates-001/verify.groovy @@ -1,10 +1,43 @@ -def output1 = new File( basedir, "output1.txt").text +import groovy.json.JsonSlurper +import groovy.xml.XmlSlurper + +def output1 = new File(basedir, "output1.txt").text assert output1 =~ /\Qlocalhost:dummy-maven-plugin\E\s*\.*\s*\Q1.0\E\s+->\s+\Q3.1\E/ assert output1 =~ /\Qlocalhost:dummy-api\E\s*\.*\s*\Q1.0\E\s+->\s+\Q3.0\E/ -def output2 = new File( basedir, "output2.txt") +def output2 = new File(basedir, "output2.txt") assert !output2.exists() -def output3 = new File( basedir, "output3.txt").text +def output3 = new File(basedir, "output3.txt").text assert output3 =~ /\Qlocalhost:dummy-maven-plugin\E\s*\.*\s*\Q1.0\E\s+->\s+\Q3.1\E/ -assert !( output3 =~ /\Qlocalhost:dummy-api\E\s*\.*\s*\Q1.0\E\s+->\s+\Q3.0\E/ ) +assert !(output3 =~ /\Qlocalhost:dummy-api\E\s*\.*\s*\Q1.0\E\s+->\s+\Q3.0\E/) + +def changeRecorderLog = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changeRecorderLog.updates.@goal == "display-extension-updates" +assert !changeRecorderLog.updates.@date.isEmpty() +assert changeRecorderLog.updates.extensionUpdate.any {node -> + node.@groupId == 'localhost' + && node.@artifactId == 'dummy-maven-plugin' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.1' +} +assert changeRecorderLog.updates.extensionUpdate.any {node -> + node.@groupId == 'localhost' + && node.@artifactId == 'dummy-api' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} + +def jsonChanges = new JsonSlurper().parse(new File(basedir, 'target/versions-changes.json')) +assert jsonChanges.updates[0].goal == "display-extension-updates" +assert jsonChanges.updates[0].versionChanges.any {node -> + node.updateClass == 'extension' + && node.groupId == 'localhost' + && node.artifactId == 'dummy-maven-plugin' + && node.oldVersion == '1.0' + && node.newVersion == '3.1' +} + +def csvChanges = new File(basedir, 'target/versions-changes.csv').text +assert csvChanges =~ "[^;]+;display-extension-updates;[^;]+;extension;;localhost;dummy-maven-plugin;;1.0;3.1;" +assert csvChanges =~ "[^;]+;display-extension-updates;[^;]+;extension;;localhost;dummy-api;;1.0;3.0;" diff --git a/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/invoker.properties b/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/invoker.properties index d71819f43b..28c85baea0 100644 --- a/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/invoker.properties +++ b/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/invoker.properties @@ -17,5 +17,12 @@ # under the License. # -invoker.goals = ${project.groupId}:${project.artifactId}:${project.version}:display-parent-updates -invoker.mavenOpts = -Dversions.outputFile=./output.txt -DoutputEncoding=UTF-8 +invoker.goals.1 = ${project.groupId}:${project.artifactId}:${project.version}:display-parent-updates +invoker.mavenOpts.1 = -Dversions.outputFile=./output.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false + +invoker.goals.2 = ${project.groupId}:${project.artifactId}:${project.version}:display-parent-updates +invoker.mavenOpts.2 = -Dversions.outputFile=./output.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=json + +invoker.goals.3 = ${project.groupId}:${project.artifactId}:${project.version}:display-parent-updates +invoker.mavenOpts.3 = -Dversions.outputFile=./output.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=csv + diff --git a/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/verify.groovy b/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/verify.groovy index 1384c8e659..c195de5834 100644 --- a/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/verify.groovy +++ b/versions-maven-plugin/src/it/it-display-parent-updates-simple-update/verify.groovy @@ -1,2 +1,30 @@ +import groovy.xml.XmlSlurper +import groovy.json.JsonSlurper + def output = new File(basedir, "output.txt").text assert output =~ /\Qlocalhost:dummy-parent2\E\s*\.*\s*\Q1.0\E\s+->\s+\Q3.1\E\b/ + +def changeRecorderLog = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changeRecorderLog.updates.@goal == "display-parent-updates" +assert !changeRecorderLog.updates.@date.isEmpty() +assert changeRecorderLog.updates.dependencyUpdate.any {node -> + node.@kind == 'parent-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-parent2' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.1' +} + +def jsonChanges = new JsonSlurper().parse(new File(basedir, 'target/versions-changes.json')) +assert jsonChanges.updates[0].goal == "display-parent-updates" +assert jsonChanges.updates[0].versionChanges.any { node -> + node.updateClass == 'dependency' + && node.kind == 'parent-update' + && node.groupId == 'localhost' + && node.artifactId == 'dummy-parent2' + && node.oldVersion == '1.0' + && node.newVersion == '3.1' +} + +def csvChanges = new File(basedir, 'target/versions-changes.csv').text +assert csvChanges =~ "[^;]+;display-parent-updates;[^;]+;dependency;parent-update;localhost;dummy-parent2;;1.0;3.1;" diff --git a/versions-maven-plugin/src/it/it-display-plugin-updates-001/invoker.properties b/versions-maven-plugin/src/it/it-display-plugin-updates-001/invoker.properties index bef19502c7..356eff61d1 100644 --- a/versions-maven-plugin/src/it/it-display-plugin-updates-001/invoker.properties +++ b/versions-maven-plugin/src/it/it-display-plugin-updates-001/invoker.properties @@ -1,6 +1,8 @@ invoker.goals.1=${project.groupId}:${project.artifactId}:${project.version}:display-plugin-updates -invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 +invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false invoker.goals.2=${project.groupId}:${project.artifactId}:${project.version}:display-plugin-updates -invoker.mavenOpts.2 = -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -Dmaven.version.ignore=3.0 +invoker.mavenOpts.2 = -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -Dmaven.version.ignore=3.0 -DchangeRecorderFormat=json +invoker.goals.3=${project.groupId}:${project.artifactId}:${project.version}:display-plugin-updates +invoker.mavenOpts.3 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DchangeRecorderFormat=csv diff --git a/versions-maven-plugin/src/it/it-display-plugin-updates-001/verify.groovy b/versions-maven-plugin/src/it/it-display-plugin-updates-001/verify.groovy index 765fed6879..a5a16a9136 100644 --- a/versions-maven-plugin/src/it/it-display-plugin-updates-001/verify.groovy +++ b/versions-maven-plugin/src/it/it-display-plugin-updates-001/verify.groovy @@ -1,6 +1,48 @@ +import groovy.json.JsonSlurper +import groovy.xml.XmlSlurper + output = new File(basedir, "output1.txt").text assert output =~ /\Qlocalhost:dummy-maven-plugin\E\s*\.*\s*1\.0\s+->\s+3\.0\b/ output = new File(basedir, "output2.txt").text assert ! ( output =~ /\Qlocalhost:dummy-maven-plugin\E\s*\.*\s*1\.0\s+->\s+3\.0\b/ ) assert output =~ /\Qlocalhost:dummy-maven-plugin\E\s*\.*\s*1\.0\s+->\s+2\.1\b/ + +def changeRecorderLog = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changeRecorderLog.updates.@goal == "display-plugin-updates" +assert !changeRecorderLog.updates.@date.isEmpty() +assert changeRecorderLog.updates.pluginUpdate.any {node -> + node.@groupId == 'localhost' + && node.@artifactId == 'dummy-maven-plugin' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.0' +} +assert changeRecorderLog.updates.pluginUpdate.any {node -> + node.@groupId == 'localhost' + && node.@artifactId == 'dummy-maven-plugin' + && node.@oldVersion == '1.0' + && node.@newVersion == '3.1' + && node.@minimumMavenVersion == '3.8.4' +} + +def jsonChanges = new JsonSlurper().parse(new File(basedir, 'target/versions-changes.json')) +assert jsonChanges.updates[0].goal == "display-plugin-updates" +assert jsonChanges.updates[0].versionChanges.any {node -> + node.updateClass == 'plugin' + && node.groupId == 'localhost' + && node.artifactId == 'dummy-maven-plugin' + && node.oldVersion == '1.0' + && node.newVersion == '2.1' +} +assert jsonChanges.updates[0].versionChanges.any {node -> + node.updateClass == 'plugin' + && node.groupId == 'localhost' + && node.artifactId == 'dummy-maven-plugin' + && node.oldVersion == '1.0' + && node.newVersion == '3.1' + && node.minimumMavenVersion == '3.8.4' +} + +def csvChanges = new File(basedir, 'target/versions-changes.csv').text +assert csvChanges =~ "[^;]+;display-plugin-updates;[^;]+;plugin;;localhost;dummy-maven-plugin;;1.0;3.0;" +assert csvChanges =~ "[^;]+;display-plugin-updates;[^;]+;plugin;;localhost;dummy-maven-plugin;;1.0;3.1;3.8.4" diff --git a/versions-maven-plugin/src/it/it-display-property-updates-001/invoker.properties b/versions-maven-plugin/src/it/it-display-property-updates-001/invoker.properties index 2b9ac63e46..6da513b081 100644 --- a/versions-maven-plugin/src/it/it-display-property-updates-001/invoker.properties +++ b/versions-maven-plugin/src/it/it-display-property-updates-001/invoker.properties @@ -1,5 +1,11 @@ invoker.goals.1 = ${project.groupId}:${project.artifactId}:${project.version}:display-property-updates -invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DautoLinkItems=true +invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DautoLinkItems=true -DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false invoker.goals.2 = ${project.groupId}:${project.artifactId}:${project.version}:display-property-updates invoker.mavenOpts.2 = -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -DautoLinkItems=true -Dmaven.version.ignore=2.0 + +invoker.goals.3 = ${project.groupId}:${project.artifactId}:${project.version}:display-property-updates +invoker.mavenOpts.3 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DautoLinkItems=true -DchangeRecorderFormat=json + +invoker.goals.4 = ${project.groupId}:${project.artifactId}:${project.version}:display-property-updates +invoker.mavenOpts.4 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8 -DautoLinkItems=true -DchangeRecorderFormat=csv diff --git a/versions-maven-plugin/src/it/it-display-property-updates-001/verify.groovy b/versions-maven-plugin/src/it/it-display-property-updates-001/verify.groovy index 53dab60be1..d1f50c1518 100644 --- a/versions-maven-plugin/src/it/it-display-property-updates-001/verify.groovy +++ b/versions-maven-plugin/src/it/it-display-property-updates-001/verify.groovy @@ -1,5 +1,43 @@ +import groovy.json.JsonSlurper +import groovy.xml.XmlSlurper + output = new File(basedir, "output1.txt").text assert output =~ /\Q\u0024{api}\E\s*\.*\s*1\.0\s+->\s+2\.0\b/ output = new File(basedir, "output2.txt").text assert ! ( output =~ /\Q\u0024{api}\E\s*\.*\s*1\.0\s+->\s+2\.0\b/ ) + +def changeRecorderLog = new XmlSlurper().parse(new File(basedir, 'target/versions-changes.xml')) +assert changeRecorderLog.updates.@goal == "display-property-updates" +assert !changeRecorderLog.updates.@date.isEmpty() +assert changeRecorderLog.updates.propertyUpdate.any {node -> + node.@property == 'api' + && node.@oldValue == '1.0' + && node.@newValue == '2.0' +} +assert changeRecorderLog.updates.dependencyUpdate.any {node -> + node.@kind == 'property-update' + && node.@groupId == 'localhost' + && node.@artifactId == 'dummy-api' + && node.@oldVersion == '1.0' + && node.@newVersion == '2.0' +} + +def jsonChanges = new JsonSlurper().parse(new File(basedir, 'target/versions-changes.json')) +assert jsonChanges.updates[0].goal == "display-property-updates" +assert jsonChanges.updates[0].versionChanges.any {node -> + node.property == 'api' + node.oldValue == '1.0' + node.newValue == '2.0' +} +assert jsonChanges.updates[0].versionChanges.any {node -> + node.kind == 'property-update' + node.groupId == 'localhost' + node.artifactId == 'dummy-api' + node.oldVersion == '1.0' + node.newVersion == '2.0' +} + +def csvChanges = new File(basedir, 'target/versions-changes.csv').text +assert csvChanges =~ "[^;]+;display-property-updates;[^;]+;property;;;;api;1.0;2.0;" +assert csvChanges =~ "[^;]+;display-property-updates;[^;]+;dependency;property-update;localhost;dummy-api;;1.0;2.0;" diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java index d56d0d7efc..88ef440fb2 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java @@ -23,10 +23,10 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.model.Dependency; @@ -39,14 +39,14 @@ import org.apache.maven.shared.artifact.filter.ScopeArtifactFilter; import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.codehaus.mojo.versions.recording.DefaultDependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; -import org.codehaus.mojo.versions.utils.DependencyComparator; +import org.codehaus.mojo.versions.utils.VersionStringComparator; import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.util.version.GenericVersionScheme; /** * Base class for a mojo that updates dependency versions. @@ -65,6 +65,8 @@ public abstract class AbstractVersionsDependencyUpdaterMojo extends AbstractVers */ protected static final Pattern SNAPSHOT_REGEX = Pattern.compile("^(.+)-((SNAPSHOT)|(\\d{8}\\.\\d{6}-\\d+))$"); + private final GenericVersionScheme versionScheme; + /** * A comma separated list of artifact patterns to include. Follows the pattern * "groupId:artifactId:type:classifier:version". Designed to allow specifying the set of includes from the command @@ -140,7 +142,7 @@ public abstract class AbstractVersionsDependencyUpdaterMojo extends AbstractVers * @param artifactFactory {@link ArtifactFactory} bean instance * @param repositorySystem {@link RepositorySystem} bean instance * @param wagonMap a map of {@link Wagon} instances per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException thrown if an error occurs */ @Inject @@ -148,9 +150,10 @@ protected AbstractVersionsDependencyUpdaterMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); + this.versionScheme = new GenericVersionScheme(); } /** @@ -220,24 +223,23 @@ protected Optional findArtifact(Dependency dependency) { * * @param dependency Dependency * @return Artifact - * @throws MojoExecutionException Mojo execution exception * @since 1.0-alpha-3 */ - protected Artifact toArtifact(Dependency dependency) throws MojoExecutionException { + protected Artifact toArtifact(Dependency dependency) { return findArtifact(dependency).orElse(artifactFactory.createArtifact(dependency)); } /** * Try to find the artifact that matches the given parent model. - * @param model Parent model - * @return Artifact for the parent - * @throws MojoExecutionException thrown if the dependency cannot be converted to an artifacted + * + * @param parentModel {@link Parent} object representing the parent model + * @return Artifact representing the parent */ - protected Artifact toArtifact(Parent model) throws MojoExecutionException { + protected Artifact toArtifact(Parent parentModel) { return this.toArtifact(DependencyBuilder.newBuilder() - .withGroupId(model.getGroupId()) - .withArtifactId(model.getArtifactId()) - .withVersion(model.getVersion()) + .withGroupId(parentModel.getGroupId()) + .withArtifactId(parentModel.getArtifactId()) + .withVersion(parentModel.getVersion()) .withType("pom") .withScope(Artifact.SCOPE_COMPILE) .build()); @@ -326,7 +328,7 @@ protected boolean isProducedByReactor(Dependency dependency) { * @return true if project and dep refer to the same artifact */ private boolean compare(MavenProject project, Dependency dep) { - if (!StringUtils.equals(project.getGroupId(), dep.getGroupId())) { + if (!Objects.equals(project.getGroupId(), dep.getGroupId())) { return false; } return project.getArtifactId().equals(dep.getArtifactId()); @@ -341,16 +343,16 @@ private boolean compare(MavenProject project, Dependency dep) { * @return true if artifact and dep refer to the same artifact */ private boolean compare(Artifact artifact, Dependency dep) { - if (!StringUtils.equals(artifact.getGroupId(), dep.getGroupId())) { + if (!Objects.equals(artifact.getGroupId(), dep.getGroupId())) { return false; } - if (!StringUtils.equals(artifact.getArtifactId(), dep.getArtifactId())) { + if (!Objects.equals(artifact.getArtifactId(), dep.getArtifactId())) { return false; } - if (!StringUtils.equals(artifact.getType(), dep.getType())) { + if (!Objects.equals(artifact.getType(), dep.getType())) { return false; } - return StringUtils.equals(artifact.getClassifier(), dep.getClassifier()); + return Objects.equals(artifact.getClassifier(), dep.getClassifier()); } /** @@ -488,89 +490,59 @@ private int findFirstChar(final String includeString, final String chars) { * * @param project {@link MavenProject} being updated * @param pom {@link MutableXMLStreamReader} instance to update the POM XML document - * @param dep dependency to be updated (can also be a dependency made from the parent) - * @param newVersion new version to update the dependency to - * @param changeKind title for the {@link ChangeRecorder} log + * @param change {@link DependencyVersionChange} object describing the change * @return {@code true} if an update has been made, {@code false} otherwise * @throws XMLStreamException thrown if updating the XML doesn't succeed - * @throws MojoExecutionException thrown if the dependency cannot be converted to an artifact */ protected boolean updateDependencyVersion( - MavenProject project, - MutableXMLStreamReader pom, - Dependency dep, - String newVersion, - DependencyChangeRecord.ChangeKind changeKind) - throws XMLStreamException, MojoExecutionException { + MavenProject project, MutableXMLStreamReader pom, DependencyVersionChange change) + throws XMLStreamException { boolean updated = false; - if (getProcessParent() - && project.getParent() != null - && (DependencyComparator.INSTANCE.compare( - dep, - DependencyBuilder.newBuilder() - .withGroupId(getProject() - .getParentArtifact() - .getGroupId()) - .withArtifactId(getProject() - .getParentArtifact() - .getArtifactId()) - .withVersion(getProject() - .getParentArtifact() - .getVersion()) - .build()) - == 0 - || getProject().getParentArtifact().getBaseVersion() != null - && DependencyComparator.INSTANCE.compare( - dep, - DependencyBuilder.newBuilder() - .withGroupId(getProject() - .getParentArtifact() - .getGroupId()) - .withArtifactId(getProject() - .getParentArtifact() - .getArtifactId()) - .withVersion(getProject() - .getParentArtifact() - .getBaseVersion()) - .build()) - == 0)) { - if (PomHelper.setProjectParentVersion(pom, newVersion)) { - if (getLog().isDebugEnabled()) { - getLog().debug("Made parent update from " + dep.getVersion() + " to " + newVersion); + if (getProcessParent() && project.getParent() != null) { + Artifact parent = project.getParentArtifact(); + if (Objects.equals(change.getGroupId(), parent.getGroupId()) + && Objects.equals(change.getArtifactId(), parent.getArtifactId()) + && (VersionStringComparator.STRICT.compare(change.getOldVersion(), parent.getVersion()) == 0 + || VersionStringComparator.STRICT.compare(change.getOldVersion(), parent.getBaseVersion()) + == 0)) { + if (PomHelper.setProjectParentVersion(pom, change.getNewVersion())) { + if (getLog().isDebugEnabled()) { + getLog().debug("Made parent update from " + change.getOldVersion() + " to " + + change.getNewVersion()); + } + updated = true; + } else { + getLog().warn("Could not update parent from " + change.getOldVersion() + " to " + + change.getNewVersion()); } - getChangeRecorder() - .recordChange(DefaultDependencyChangeRecord.builder() - .withKind(changeKind) - .withDependency(dep) - .withNewVersion(newVersion) - .build()); - updated = true; - } else { - getLog().warn("Could not update parent: " + dep.toString() + " to " + newVersion); } } if (PomHelper.setDependencyVersion( pom, - dep.getGroupId(), - dep.getArtifactId(), - dep.getVersion(), - newVersion, + change.getGroupId(), + change.getArtifactId(), + change.getOldVersion(), + change.getNewVersion(), getProject().getModel(), getLog())) { if (getLog().isInfoEnabled()) { - getLog().info("Updated " + toString(dep) + " to version " + newVersion + " in " + project.getGroupId() - + ":" + project.getArtifactId() + ":" + project.getVersion()); + getLog().info(String.format( + "Updated %s:%s:%s to version %s in %s:%s:%s", + change.getGroupId(), + change.getArtifactId(), + change.getOldVersion(), + change.getNewVersion(), + project.getGroupId(), + project.getArtifact(), + project.getVersion())); } - getChangeRecorder() - .recordChange(DefaultDependencyChangeRecord.builder() - .withKind(changeKind) - .withDependency(dep) - .withNewVersion(newVersion) - .build()); updated = true; } + if (updated) { + getChangeRecorder().recordChange(change); + } return updated; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java index d47a6ae732..dc734cff74 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java @@ -33,7 +33,7 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -103,7 +103,7 @@ public abstract class AbstractVersionsDisplayMojo extends AbstractVersionsUpdate * @param artifactFactory a {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of {@link Wagon} instances per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException thrown if an error occurs */ @Inject @@ -111,9 +111,9 @@ protected AbstractVersionsDisplayMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } /** diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java index e2b92bd3cf..adc8867748 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java @@ -27,10 +27,13 @@ import java.io.Writer; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.ArtifactResolutionException; @@ -53,7 +56,8 @@ import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.model.RuleSet; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; @@ -138,32 +142,66 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { protected MojoExecution mojoExecution; /** - * The format used to record changes. If "none" is specified, no changes are recorded. + *

The format used to record changes. The following formats are supported:

+ *
    + *
  • {@code none}: will not output any changes
  • + *
  • {@code xml}: outputs changes to an XML format. + *

    If no {@link #changeRecorderOptions} are provided, + * or if the {@code legacy} option is not specified, or if {@code legacy=true} is provided as an option, + * the "legacy" format conforming to the + * {@code "http://www.mojohaus.org/versions-maven-plugin/schema/updates/2.0"} namespace will be selected.

    + *

    If the options contain {@code legacy=false}, the new renderer is used, conforming to + * {@code "http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0"}

    + *
  • + *
  • {@code json} outputs changes to a Json file
  • + *
  • {@code csv} outputs changes to a CSV file
  • + *
* * @since 2.11 */ @Parameter(property = "changeRecorderFormat", defaultValue = "none") private String changeRecorderFormat = "none"; + + /** + *

Optional options to be passed to the selected change recorder.

+ *

The format of the options is a string consisting of a {@code key=value} pairs divided by colon ({@code :}) + * signs, e.g. {@code key0=value0:key1=value1:key2=value2}. + * + * @since 2.20 + */ + @Parameter(property = "changeRecorderOptions") + private String changeRecorderOptions; + /** * The output file used to record changes. + * Default value is {@code ${project.build.directory}/versions-changes.}, + * where {@code } is provided by the respective format handler. * * @since 2.11 + * @deprecated use #changeRecorderOutputFileName */ - @Parameter(property = "changeRecorderOutputFile", defaultValue = "${project.build.directory}/versions-changes.xml") + @Parameter(property = "changeRecorderOutputFile") + @Deprecated private File changeRecorderOutputFile; /** - * The change recorders implementation. + * The output file name used to create a change recorder file within {@code ${project.build.directory}} + * (which usually resolves to {@code target}). + * Default value is {@code versions-changes.}, + * where {@code } is provided by the respective format handler. + * + * @since 2.20 */ - private Map changeRecorders; + @Parameter(property = "changeRecorderOutputFileName") + private String changeRecorderOutputFileName; /** *

Allows specifying the {@linkplain RuleSet} object describing rules * on artifact versions to ignore when considering updates.

* - * @see - * Using the ruleSet element in the POM - * + * @see + * Using the ruleSet element in the POM * @since 2.13.0 */ @Parameter @@ -173,12 +211,11 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { *

Allows specifying ignored versions directly as an alternative * to providing the {@linkplain #ruleSet} parameter; mainly created * for {@code -D} property usage.

- * *

* Example: {@code "1\.0\.1,.+-M.,.*-SNAPSHOT"} *

- * *

Currently, this parameter will override the defined {@link #ruleSet}

+ * * @since 2.13.0 */ @Parameter(property = "maven.version.ignore") @@ -196,6 +233,10 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { */ protected final ArtifactFactory artifactFactory; + private final Map changeRecorderFactories; + + private VersionChangeRecorder changeRecorder; + // --------------------- GETTER / SETTER METHODS --------------------- /** @@ -204,7 +245,7 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap map of wagon instances - * @param changeRecorders map of change recorders + * @param changeRecorderFactories map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -212,12 +253,13 @@ protected AbstractVersionsUpdaterMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { this.artifactFactory = artifactFactory; this.repositorySystem = repositorySystem; this.wagonMap = wagonMap; - this.changeRecorders = changeRecorders; + // the actual factory is only known in the child class + this.changeRecorderFactories = changeRecorderFactories; } /** @@ -317,6 +359,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { * @throws MojoExecutionException thrown if any of input parameters is invalid */ protected void validateInput() throws MojoExecutionException {} + /** * Finds the latest version of the specified artifact that matches the version range. * @@ -325,9 +368,9 @@ protected void validateInput() throws MojoExecutionException {} * @param allowingSnapshots null for no override, otherwise the local override to apply. * @param usePluginRepositories Use plugin repositories * @return The latest version of the specified artifact that matches the specified version range or - * null if no matching version could be found. + * null if no matching version could be found. * @throws VersionRetrievalException If the artifact metadata could not be found. - * @throws MojoExecutionException if something goes wrong. + * @throws MojoExecutionException if something goes wrong. * @since 1.0-alpha-1 */ protected ArtifactVersion findLatestVersion( @@ -399,10 +442,10 @@ protected abstract void update(MutableXMLStreamReader pom) * @return true if the update should be applied. * @since 1.0-alpha-1 * @deprecated This method no longer supported. - * use shouldApplyUpdate( Artifact artifact, String currentVersion, ArtifactVersion updateVersion, Boolean - * forceUpdate ) - *

- * Returns true if the update should be applied. + * use shouldApplyUpdate( Artifact artifact, String currentVersion, ArtifactVersion updateVersion, Boolean + * forceUpdate ) + *

+ * Returns true if the update should be applied. */ @Deprecated protected boolean shouldApplyUpdate(Artifact artifact, String currentVersion, ArtifactVersion updateVersion) { @@ -450,17 +493,18 @@ protected boolean shouldApplyUpdate( /** * Attempts to update the property to a newer version, if that exists - * @param pom pom to update - * @param property property to update - * @param version {@link PropertyVersions} object - * @param currentVersion current version - * @param allowDowngrade if downgrades should be allowed if snapshots are not allowed - * @param unchangedSegment most major segment not to be changed + * + * @param pom pom to update + * @param property property to update + * @param version {@link PropertyVersions} object + * @param currentVersion current version + * @param allowDowngrade if downgrades should be allowed if snapshots are not allowed + * @param unchangedSegment most major segment not to be changed * @return new version of the artifact, if the property was updated; {@code null} if there was no update - * @throws XMLStreamException thrown from {@link MutableXMLStreamReader} if the update doesn't succeed + * @throws XMLStreamException thrown from {@link MutableXMLStreamReader} if the update doesn't + * succeed * @throws InvalidVersionSpecificationException thrown if {@code unchangedSegment} doesn't match the version - * @throws InvalidSegmentException thrown if {@code unchangedSegment} is invalid - * @throws MojoExecutionException thrown if any other error occurs + * @throws InvalidSegmentException thrown if {@code unchangedSegment} is invalid */ protected ArtifactVersion updatePropertyToNewestVersion( MutableXMLStreamReader pom, @@ -469,8 +513,7 @@ protected ArtifactVersion updatePropertyToNewestVersion( String currentVersion, boolean allowDowngrade, Optional unchangedSegment) - throws XMLStreamException, InvalidVersionSpecificationException, InvalidSegmentException, - MojoExecutionException { + throws XMLStreamException, InvalidVersionSpecificationException, InvalidSegmentException { ArtifactVersion winner = version.getNewestVersion( currentVersion, property, getAllowSnapshots(), this.reactorProjects, allowDowngrade, unchangedSegment); @@ -484,32 +527,76 @@ protected ArtifactVersion updatePropertyToNewestVersion( return null; } + /** + * Parses the {@link #changeRecorderOptions} into a map of key-value pairs. + * + * @return the parsed options or {@code null} if no options were provided + * @throws IllegalArgumentException if the options are malformed + */ + protected Map getChangeRecorderOptions() { + if (changeRecorderOptions == null) { + return null; + } + return Arrays.stream(changeRecorderOptions.split(":")) + .map(option -> { + String[] kv = option.split("="); + if (kv.length != 2) { + throw new IllegalArgumentException("Invalid value of changeRecorderOptions (" + + changeRecorderOptions + "): each option must" + + " be a key=value pair, but \"" + option + "\" isn't."); + } + return kv; + }) + .collect(Collectors.toMap(kv -> kv[0], kv -> kv[1])); + } + /** * Configure and return the change recorder. * * @return The change recorder - * @throws MojoExecutionException if something goes wrong. */ - protected ChangeRecorder getChangeRecorder() throws MojoExecutionException { - ChangeRecorder changeRecorder = changeRecorders.get(changeRecorderFormat); + protected synchronized VersionChangeRecorder getChangeRecorder() { if (changeRecorder == null) { - throw new MojoExecutionException( - "Only " + changeRecorders.keySet() + " formats are supported for change recordings"); + VersionChangeRecorderFactory factory = changeRecorderFactories.get(changeRecorderFormat); + if (factory == null) { + throw new IllegalStateException( + "Only " + changeRecorderFactories.keySet() + " formats are supported for change recordings"); + } + changeRecorder = factory.create(session, mojoExecution, getLog(), getChangeRecorderOptions()); } return changeRecorder; } /** - * Save all of the changes recorded by the change recorder. + * Provides the effective change recorder output file name * - * @throws IOException On I/O errors - * @throws MojoExecutionException if something goes wrong. - */ - protected void saveChangeRecorderResults() throws IOException, MojoExecutionException { + * @return effective change recorder output file name + */ + protected Path getChangeRecorderOutputFile() { + if (changeRecorderOutputFileName != null) { + return getProject() + .getBasedir() + .toPath() + .resolve(getProject().getBuild().getDirectory()) + .resolve(changeRecorderOutputFileName); + } else if (changeRecorderOutputFile != null) { + return changeRecorderOutputFile.toPath(); + } + return getProject() + .getBasedir() + .toPath() + .resolve(getProject().getBuild().getDirectory()) + .resolve(getChangeRecorder().getDefaultFileName()); + } - this.getLog().debug("writing change record to " + this.changeRecorderOutputFile); - getChangeRecorder() - .writeReport( - ofNullable(changeRecorderOutputFile).map(File::toPath).orElse(null)); + /** + * Save all the changes recorded by the change recorder. + * + * @throws IOException On I/O errors + * @throws IllegalStateException if the selected change recorder is not supported + */ + protected void saveChangeRecorderResults() throws IOException { + Path outputFile = getChangeRecorderOutputFile(); + getChangeRecorder().writeReport(outputFile); } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java index b17a6596f2..e18a5f50d5 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java @@ -26,8 +26,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.model.Dependency; @@ -45,15 +46,22 @@ import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.PropertyVersions; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; +import org.codehaus.mojo.versions.model.VersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; +import org.codehaus.mojo.versions.utils.VersionStringComparator; import org.eclipse.aether.RepositorySystem; import static java.util.Collections.singletonList; import static java.util.Optional.ofNullable; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PARENT_UPDATE; /** * Compare dependency versions of the current project to dependencies or dependency management of a remote repository @@ -155,7 +163,7 @@ public class CompareDependenciesMojo extends AbstractVersionsDependencyUpdaterMo * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol * @param projectBuilder a {@link ProjectBuilder} instance - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -164,9 +172,9 @@ public CompareDependenciesMojo( RepositorySystem repositorySystem, Map wagonMap, ProjectBuilder projectBuilder, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); this.projectBuilder = projectBuilder; } @@ -234,30 +242,25 @@ protected void update(MutableXMLStreamReader pom) remoteMavenProject.getDependencies().forEach(dep -> remoteDepsMap.putIfAbsent(dep.getManagementKey(), dep)); } - List totalDiffs = new ArrayList<>(); - List propertyDiffs = new ArrayList<>(); + List versionChanges = new ArrayList<>(); if (getProject().getDependencyManagement() != null && getProcessDependencyManagement()) { - totalDiffs.addAll(compareVersions( + versionChanges.addAll(compareVersions( getProject(), pom, getProject().getDependencyManagement().getDependencies(), remoteDepsMap, - DependencyChangeRecord.ChangeKind.DEPENDENCY_MANAGEMENT)); + DEPENDENCY_MANAGEMENT_UPDATE)); } if (getProject().getDependencies() != null && getProcessDependencies()) { - totalDiffs.addAll(compareVersions( - getProject(), - pom, - getProject().getDependencies(), - remoteDepsMap, - DependencyChangeRecord.ChangeKind.DEPENDENCY)); + versionChanges.addAll(compareVersions( + getProject(), pom, getProject().getDependencies(), remoteDepsMap, DEPENDENCY_UPDATE)); } if (updatePropertyVersions) { Map versionProperties = this.getHelper() .getVersionPropertiesMap(VersionsHelper.VersionPropertiesMapRequest.builder() .withMavenProject(getProject()) .build()); - propertyDiffs.addAll(updatePropertyVersions(pom, versionProperties, remoteDepsMap)); + versionChanges.addAll(updatePropertyVersions(pom, versionProperties, remoteDepsMap)); } if (getProject().getParent() != null && remoteMavenProject.getParent() != null && getProcessParent()) { Dependency parent = DependencyBuilder.newBuilder() @@ -272,22 +275,26 @@ protected void update(MutableXMLStreamReader pom) getLog().debug("Processing parent dependency: " + parent); } remoteDepsMap.putIfAbsent(parent.getManagementKey(), parent); - totalDiffs.addAll(compareVersions( - getProject(), - pom, - singletonList(getParentDependency()), - remoteDepsMap, - DependencyChangeRecord.ChangeKind.PARENT)); + versionChanges.addAll(compareVersions( + getProject(), pom, singletonList(getParentDependency()), remoteDepsMap, PARENT_UPDATE)); } + List dependencyDiffs = versionChanges.stream() + .filter(change -> !(change instanceof PropertyVersionChange)) + .map(change -> (DependencyVersionChange) change) + .map(this::writeDependencyDiffMessage) + .collect(Collectors.toList()); + List propertyDiffs = versionChanges.stream() + .filter(change -> (change instanceof PropertyVersionChange)) + .map(change -> (PropertyVersionChange) change) + .map(change -> writeDiffMessage(change.getProperty(), change.getOldValue(), change.getNewValue())) + .collect(Collectors.toList()); if (reportMode) { getLog().info("The following differences were found:"); - if (totalDiffs.isEmpty()) { + if (dependencyDiffs.isEmpty()) { getLog().info(" none"); } else { - for (String totalDiff : totalDiffs) { - getLog().info(" " + totalDiff); - } + dependencyDiffs.forEach(diff -> getLog().info(" " + diff)); } getLog().info("The following property differences were found:"); if (propertyDiffs.isEmpty()) { @@ -300,22 +307,22 @@ protected void update(MutableXMLStreamReader pom) } if (reportOutputFile != null) { - writeReportFile(totalDiffs, propertyDiffs); + writeReportFile(dependencyDiffs, propertyDiffs); } } /** * Builds a {@link MavenProject} instance for the dependency with a given {@code groupId}, * {@code artifactId}, and {@code version}. - * @param groupId {@code groupId} of the dependency + * + * @param groupId {@code groupId} of the dependency * @param artifactId {@code artifactId} of the dependency - * @param version {@code version} of the dependency + * @param version {@code version} of the dependency * @return retrieved {@link MavenProject} instance for the given dependency - * @throws MojoExecutionException thrown if the artifact for the dependency could not be constructed * @throws ProjectBuildingException thrown if the {@link MavenProject} instance could not be constructed */ private MavenProject getRemoteMavenProject(String groupId, String artifactId, String version) - throws MojoExecutionException, ArtifactResolutionException, ProjectBuildingException { + throws ArtifactResolutionException, ProjectBuildingException { Artifact remoteArtifact = toArtifact(DependencyBuilder.newBuilder() .withGroupId(groupId) .withArtifactId(artifactId) @@ -340,17 +347,16 @@ private MavenProject getRemoteMavenProject(String groupId, String artifactId, St /** * Compare the dependency versions of the current project with the dependency versions of a remote project * - * @throws XMLStreamException - * @throws MojoExecutionException + * @throws XMLStreamException thrown if updating the XML doesn't succeed */ - private List compareVersions( + private List compareVersions( MavenProject project, MutableXMLStreamReader pom, List dependencies, Map remoteDependencies, - DependencyChangeRecord.ChangeKind changeKind) - throws MojoExecutionException, XMLStreamException { - List updates = new ArrayList<>(); + DependencyChangeKind dependencyChangeKind) + throws XMLStreamException { + List updates = new ArrayList<>(); for (Dependency dep : dependencies) { Artifact artifact = this.toArtifact(dep); if (!isIncluded(artifact)) { @@ -360,11 +366,16 @@ private List compareVersions( Dependency remoteDep = remoteDependencies.get(dep.getManagementKey()); if (remoteDep != null) { String remoteVersion = remoteDep.getVersion(); - if (!Objects.equals(remoteVersion, dep.getVersion())) { - StringBuilder buf = writeDependencyDiffMessage(dep, remoteVersion); - updates.add(buf.toString()); + if (VersionStringComparator.STRICT.compare(remoteVersion, dep.getVersion()) != 0) { + DependencyVersionChange versionChange = new DependencyVersionChange() + .withKind(dependencyChangeKind) + .withGroupId(dep.getGroupId()) + .withArtifactId(dep.getArtifactId()) + .withOldVersion(dep.getVersion()) + .withNewVersion(remoteVersion); + updates.add(versionChange); if (!reportMode) { - updateDependencyVersion(project, pom, dep, remoteVersion, changeKind); + updateDependencyVersion(project, pom, versionChange); } } } @@ -376,12 +387,12 @@ private List compareVersions( /** * Updates the properties holding a version if necessary. */ - private List updatePropertyVersions( + private List updatePropertyVersions( MutableXMLStreamReader pom, Map versionProperties, Map remoteDependencies) throws XMLStreamException { - List result = new ArrayList<>(); + List result = new ArrayList<>(); for (Map.Entry entry : versionProperties.entrySet()) { Property property = entry.getKey(); PropertyVersions version = entry.getValue(); @@ -390,10 +401,12 @@ private List updatePropertyVersions( if (candidateVersion != null) { String originalVersion = version.getAssociations()[0].getArtifact().getVersion(); // Yekes - if (!candidateVersion.equals(originalVersion)) // Update needed + if (VersionStringComparator.LENIENT.compare(candidateVersion, originalVersion) != 0) // Update needed { - result.add(writeDiffMessage(property.getName(), originalVersion, candidateVersion) - .toString()); + result.add(new PropertyVersionChange() + .withProperty(property.getName()) + .withOldValue(originalVersion) + .withNewValue(candidateVersion)); if (!reportMode && PomHelper.setPropertyVersion(pom, null, property.getName(), candidateVersion)) { getLog().info("Updated ${" + property.getName() + "} from " + originalVersion + " to " + candidateVersion); @@ -437,10 +450,17 @@ private String computeCandidateVersion( return candidateVersion; } + /** + * @param dependenciesUpdate list of formatted dependency update log lines + * @param propertiesUpdate list of formatted property update log lines + * @throws MojoExecutionException thrown if report file or one of its parent directories cannot be created + */ private void writeReportFile(List dependenciesUpdate, List propertiesUpdate) throws MojoExecutionException { if (!reportOutputFile.getParentFile().exists()) { - reportOutputFile.getParentFile().mkdirs(); + if (!reportOutputFile.getParentFile().mkdirs()) { + throw new MojoExecutionException("Cannot create parent directories for " + reportOutputFile); + } } try (FileWriter fw = new FileWriter(reportOutputFile); // @@ -472,31 +492,24 @@ private void writeReportFile(List dependenciesUpdate, List prope /** * Create a simple message describing the version diff * - * @param dep - * @param remoteVersion + * @param change dependency version change * @return The message */ - private StringBuilder writeDependencyDiffMessage(Dependency dep, String remoteVersion) { - String id = dep.getGroupId() + ":" + dep.getArtifactId(); + private String writeDependencyDiffMessage(DependencyVersionChange change) { + String id = change.getGroupId() + ":" + change.getArtifactId(); return writeDiffMessage( id, - ofNullable(dep.getVersion()).orElse("(no version)"), - ofNullable(remoteVersion).orElse("(no version)")); + ofNullable(change.getOldVersion()).orElse("(no version)"), + ofNullable(change.getNewVersion()).orElse("(no version)")); } - private StringBuilder writeDiffMessage(String id, String originalVersion, String targetVersion) { - StringBuilder buf = new StringBuilder(); - buf.append(id); - buf.append(' '); + private String writeDiffMessage(String id, String originalVersion, String targetVersion) { int padding = INFO_PAD_SIZE - originalVersion.length() - targetVersion.length() - 4; - while (buf.length() < padding) { - buf.append('.'); - } - buf.append(' '); - buf.append(originalVersion); - buf.append(" -> "); - buf.append(targetVersion); - return buf; + int dotCount = Math.max(0, padding - (id.length() + 1)); + + String dots = StringUtils.repeat('.', dotCount); + + return id + " " + dots + " " + originalVersion + " -> " + targetVersion; } /** diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java index 37b73e9f54..0441294b18 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java @@ -21,6 +21,7 @@ import javax.inject.Inject; +import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Objects; @@ -44,10 +45,13 @@ import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.api.internal.DefaultResolverAdapter; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.filtering.WildcardMatcher; import org.codehaus.mojo.versions.internal.DependencyUpdatesLoggingHelper; import org.codehaus.mojo.versions.internal.DependencyUpdatesLoggingHelper.DependencyUpdatesResult; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.rule.RuleService; import org.codehaus.mojo.versions.rule.RulesServiceBuilder; @@ -59,6 +63,10 @@ import static java.util.Collections.emptySet; import static org.codehaus.mojo.versions.filtering.DependencyFilter.filterDependencies; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PLUGIN_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PLUGIN_UPDATE; import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromDependencyManagement; import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromPlugins; import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractPluginDependenciesFromPluginsInPluginManagement; @@ -332,7 +340,7 @@ public class DisplayDependencyUpdatesMojo extends AbstractVersionsDisplayMojo { * @param artifactFactory an {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -340,9 +348,9 @@ public DisplayDependencyUpdatesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -422,6 +430,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { INFO_PAD_SIZE + getOutputLineWidthOffset(), verbose); + VersionChangeRecorder changeRecorder = getChangeRecorder(); try { if (processDependencyManagement) { dependencyManagement = filterDependencies( @@ -471,7 +480,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { dependencyArtifactVersionsMap::get, (v1, v2) -> v1, () -> new TreeMap<>(DependencyComparator.INSTANCE))), - "Dependencies"); + DEPENDENCY_UPDATE, + changeRecorder); } if (processDependencyManagement) { @@ -483,7 +493,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { dependencyArtifactVersionsMap::get, (v1, v2) -> v1, () -> new TreeMap<>(DependencyComparator.INSTANCE))), - "Dependency Management"); + DEPENDENCY_MANAGEMENT_UPDATE, + changeRecorder); } if (processPluginDependenciesInPluginManagement) { @@ -499,7 +510,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { .collect(Collectors.toSet()), false, true); - logUpdates(loggingHelper, updates, "pluginManagement of plugins"); + logUpdates(loggingHelper, updates, PLUGIN_MANAGEMENT_UPDATE, changeRecorder); } if (processPluginDependencies) { SortedMap updates = resolverAdapter.resolveDependencyVersions( @@ -514,9 +525,10 @@ public void execute() throws MojoExecutionException, MojoFailureException { .collect(Collectors.toSet()), true, false); - logUpdates(loggingHelper, updates, "Plugin Dependencies"); + logUpdates(loggingHelper, updates, PLUGIN_UPDATE, changeRecorder); } - } catch (VersionRetrievalException e) { + saveChangeRecorderResults(); + } catch (VersionRetrievalException | IOException e) { throw new MojoExecutionException(e.getMessage(), e); } } @@ -551,8 +563,34 @@ static void validateGAVList(List gavList, int numSections, String argume private void logUpdates( DependencyUpdatesLoggingHelper loggingHelper, SortedMap versionMap, - String section) { - DependencyUpdatesResult updates = loggingHelper.getDependencyUpdates(versionMap); + DependencyChangeKind changeKind, + VersionChangeRecorder changeRecorder) { + DependencyUpdatesResult updates = loggingHelper.getDependencyUpdates( + versionMap, (dep, oldVersion, newVersion) -> new DependencyVersionChange() + .withKind(changeKind) + .withGroupId(dep.getGroupId()) + .withArtifactId(dep.getArtifactId()) + .withOldVersion(oldVersion) + .withNewVersion(newVersion)); + + String section; + switch (changeKind) { + case DEPENDENCY_UPDATE: + section = "Dependencies"; + break; + case DEPENDENCY_MANAGEMENT_UPDATE: + section = "Dependency Management"; + break; + case PLUGIN_UPDATE: + section = "Plugin Dependencies"; + break; + case PLUGIN_MANAGEMENT_UPDATE: + section = "Plugin Management Dependencies"; + break; + default: + throw new IllegalArgumentException("Unexpected section: " + changeKind); + } + if (verbose) { if (updates.getUsingLatest().isEmpty()) { if (!updates.getWithUpdates().isEmpty()) { @@ -576,6 +614,8 @@ private void logUpdates( updates.getWithUpdates().forEach(s -> logLine(false, s)); logLine(false, ""); } + + updates.getVersionChanges().forEach(changeRecorder::recordChange); } /** diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java index da2e6de41c..6c5a509843 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java @@ -42,10 +42,12 @@ import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.api.internal.DefaultResolverAdapter; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.filtering.DependencyFilter; import org.codehaus.mojo.versions.filtering.WildcardMatcher; import org.codehaus.mojo.versions.internal.DependencyUpdatesLoggingHelper; +import org.codehaus.mojo.versions.model.ExtensionVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.rule.RuleService; import org.codehaus.mojo.versions.rule.RulesServiceBuilder; @@ -167,7 +169,7 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { * @param artifactFactory an {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -175,9 +177,9 @@ public DisplayExtensionUpdatesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -252,8 +254,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { (v1, v2) -> v1, () -> new TreeMap<>(DependencyComparator.INSTANCE))); } - - logUpdates(loggingHelper, versionMap); + logUpdates(loggingHelper, versionMap, getChangeRecorder()); + saveChangeRecorderResults(); } catch (IOException | XMLStreamException | TransformerException e) { throw new MojoExecutionException(e.getMessage()); } catch (VersionRetrievalException e) { @@ -262,8 +264,15 @@ public void execute() throws MojoExecutionException, MojoFailureException { } private void logUpdates( - DependencyUpdatesLoggingHelper loggingHelper, SortedMap versionMap) { - DependencyUpdatesLoggingHelper.DependencyUpdatesResult updates = loggingHelper.getDependencyUpdates(versionMap); + DependencyUpdatesLoggingHelper loggingHelper, + SortedMap versionMap, + VersionChangeRecorder changeRecorder) { + DependencyUpdatesLoggingHelper.DependencyUpdatesResult updates = loggingHelper.getDependencyUpdates( + versionMap, (ext, oldVersion, newVersion) -> new ExtensionVersionChange() + .withGroupId(ext.getGroupId()) + .withArtifactId(ext.getArtifactId()) + .withOldVersion(oldVersion) + .withNewVersion(newVersion)); if (verbose) { if (updates.getUsingLatest().isEmpty()) { @@ -288,6 +297,8 @@ private void logUpdates( updates.getWithUpdates().forEach(s -> logLine(false, s)); logLine(false, ""); } + + updates.getVersionChanges().forEach(changeRecorder::recordChange); } /** diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java index ba3bdda39b..8c55aaa233 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java @@ -21,6 +21,7 @@ import javax.inject.Inject; +import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.Map; @@ -39,7 +40,9 @@ import org.codehaus.mojo.versions.api.ArtifactVersions; import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; @@ -150,7 +153,7 @@ public class DisplayParentUpdatesMojo extends AbstractVersionsDisplayMojo { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the wagon map - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException if any */ @Inject @@ -158,9 +161,9 @@ public DisplayParentUpdatesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -230,6 +233,19 @@ public void execute() throws MojoExecutionException, MojoFailureException { buf.append(" -> "); buf.append(artifactVersion); logLine(false, buf.toString()); + + getChangeRecorder() + .recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId(getProject().getParent().getGroupId()) + .withArtifactId(getProject().getParent().getArtifactId()) + .withOldVersion(initialVersion) + .withNewVersion(artifactVersion.toString())); + try { + saveChangeRecorderResults(); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage()); + } } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java index dec30be549..10a03d231e 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java @@ -84,7 +84,9 @@ import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.PluginVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.ArtifactVersionService; @@ -97,6 +99,7 @@ import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toMap; import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT; +import static org.codehaus.mojo.versions.api.PomHelper.APACHE_MAVEN_PLUGINS_GROUPID; /** * Displays all plugins that have newer versions available, taking care of Maven version prerequisites. @@ -196,7 +199,7 @@ public class DisplayPluginUpdatesMojo extends AbstractVersionsDisplayMojo { * @param lifecycleExecutor the (injected) instance of {@link LifecycleExecutor} * @param modelInterpolator the (injected) instance of {@link ModelInterpolator} * @param runtimeInformation the (injected) instance of {@link RuntimeInformation} - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -209,9 +212,9 @@ public DisplayPluginUpdatesMojo( LifecycleExecutor lifecycleExecutor, ModelInterpolator modelInterpolator, RuntimeInformation runtimeInformation, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); this.projectBuilder = projectBuilder; this.lifecycleExecutor = lifecycleExecutor; this.modelInterpolator = modelInterpolator; @@ -223,6 +226,57 @@ protected boolean getAllowSnapshots() { return allowSnapshots; } + private static class GroupArtifact { + private final String groupId; + private final String artifactId; + + GroupArtifact(String groupId, String artifactId) { + this.groupId = groupId; + this.artifactId = artifactId; + } + + GroupArtifact(Plugin plugin) { + this(plugin.getGroupId(), plugin.getArtifactId()); + } + + String getGroupId() { + return groupId; + } + + String getArtifactId() { + return artifactId; + } + + @Override + public int hashCode() { + return 31 + * Optional.ofNullable(groupId) + .orElse(APACHE_MAVEN_PLUGINS_GROUPID) + .hashCode() + + 37 * artifactId.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof GroupArtifact)) { + return false; + } + GroupArtifact that = (GroupArtifact) obj; + return Optional.ofNullable(groupId) + .orElse(APACHE_MAVEN_PLUGINS_GROUPID) + .equals(Optional.ofNullable(that.groupId).orElse(APACHE_MAVEN_PLUGINS_GROUPID)) + && Objects.equals(artifactId, that.artifactId); + } + + @Override + public String toString() { + return (groupId != null && !APACHE_MAVEN_PLUGINS_GROUPID.equals(groupId) ? groupId + ":" : "") + artifactId; + } + } + /** * Returns the pluginManagement section of the super-pom. * @@ -277,9 +331,7 @@ private Map getSuperPomPluginManagement() { && PATTERN_PROJECT_PLUGIN.matcher(curState.path).matches()) { result.putIfAbsent( Plugin.constructKey( - curState.groupId == null - ? PomHelper.APACHE_MAVEN_PLUGINS_GROUPID - : curState.groupId, + curState.groupId == null ? APACHE_MAVEN_PLUGINS_GROUPID : curState.groupId, curState.artifactId), curState.version); } @@ -350,6 +402,8 @@ private Map getPluginManagement(Model model) { public void execute() throws MojoExecutionException, MojoFailureException { logInit(); Set pluginsWithVersionsSpecified; + VersionChangeRecorder changeRecorder = getChangeRecorder(); + try (MutableXMLStreamReader pomReader = new MutableXMLStreamReader(getProject().getFile().toPath())) { pluginsWithVersionsSpecified = findPluginsWithVersionsSpecified(pomReader); @@ -389,7 +443,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { ArtifactVersion minMavenVersion = null; boolean superPomDrivingMinVersion = false; // if Maven prerequisite upgraded to a version, Map - Map> mavenUpgrades = new TreeMap<>(); + Map>> mavenUpgrades = new TreeMap<>(); for (Plugin plugin : plugins) { String coords = ArtifactUtils.versionlessKey(plugin.getGroupId(), plugin.getArtifactId()); @@ -481,6 +535,11 @@ public void execute() throws MojoExecutionException, MojoFailureException { effectiveVersion, " -> ", newVersion)); + changeRecorder.recordChange(new PluginVersionChange() + .withGroupId(plugin.getGroupId()) + .withArtifactId(plugin.getArtifactId()) + .withOldVersion(effectiveVersion) + .withNewVersion(newVersion)); } } @@ -562,19 +621,42 @@ public void execute() throws MojoExecutionException, MojoFailureException { } // updates if minimum Maven version is changed - for (Map.Entry> mavenUpgrade : mavenUpgrades.entrySet()) { + for (Map.Entry>> mavenUpgrade : mavenUpgrades.entrySet()) { ArtifactVersion mavenUpgradeVersion = mavenUpgrade.getKey(); - Map upgradePlugins = mavenUpgrade.getValue(); + Map> upgradePlugins = mavenUpgrade.getValue(); if (upgradePlugins.isEmpty() || compare(mavenUpgradeVersion, specMavenVersion) < 0) { continue; } logLine(false, ""); logLine(false, "Require Maven " + mavenUpgradeVersion + " to use the following plugin updates:"); - for (Map.Entry entry : upgradePlugins.entrySet()) { - logLine(false, entry.getValue()); + for (Map.Entry> entry : upgradePlugins.entrySet()) { + String effectiveVer = entry.getValue().getKey(); + String upgradedVer = entry.getValue().getValue(); + String key = + compactKey(entry.getKey().getGroupId(), entry.getKey().getArtifactId()); + if (upgradedVer != null) { + changeRecorder.recordChange(new PluginVersionChange() + .withGroupId(Optional.ofNullable(entry.getKey().getGroupId()) + .orElse(APACHE_MAVEN_PLUGINS_GROUPID)) + .withArtifactId(entry.getKey().getArtifactId()) + .withOldVersion(effectiveVer) + .withNewVersion(upgradedVer) + .withMinimumMavenVersion(mavenUpgradeVersion.toString())); + logLine( + false, + pad(key, INFO_PAD_SIZE + getOutputLineWidthOffset(), effectiveVer, " -> ", upgradedVer)); + } else { + logLine(false, pad(key, INFO_PAD_SIZE + getOutputLineWidthOffset(), effectiveVer)); + } } } logLine(false, ""); + + try { + saveChangeRecorderResults(); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage()); + } } private Pair getEffectivePluginVersion( @@ -582,7 +664,7 @@ private Pair getEffectivePluginVersion( String effectiveVersion, ArtifactVersion specMavenVersion, ArtifactVersion curMavenVersion, - Map> mavenUpgrades) + Map>> mavenUpgrades) throws MojoExecutionException, VersionRetrievalException { Artifact artifactRange = artifactFactory.createMavenPluginArtifact( plugin.getGroupId(), plugin.getArtifactId(), effectiveVersion); @@ -609,29 +691,21 @@ private Pair getEffectivePluginVersion( // newer version not compatible with current specMavenVersion: track opportunity if Maven spec // upgrade if (minRequires == null || compare(minRequires, pluginRequires) > 0) { - Map upgradePlugins = + Map> upgradePlugins = mavenUpgrades.computeIfAbsent(pluginRequires, k -> new LinkedHashMap<>()); - - String upgradePluginKey = compactKey(plugin.getGroupId(), plugin.getArtifactId()); - if (!upgradePlugins.containsKey(upgradePluginKey)) { - String newer = newerVersions[j].toString(); - if (newer.equals(effectiveVersion)) { + int finalJ = j; + String finalEffectiveVersion = effectiveVersion; + upgradePlugins.computeIfAbsent(plugin, pluginKey -> { + assert newerVersions[finalJ] != null; + String newer = newerVersions[finalJ].toString(); + if (newer.equals(finalEffectiveVersion)) { // plugin version configured that require a Maven version higher than spec - upgradePlugins.put( - upgradePluginKey, - pad(upgradePluginKey, INFO_PAD_SIZE + getOutputLineWidthOffset(), newer)); + return Pair.of(finalEffectiveVersion, null); } else { // plugin that can be upgraded - upgradePlugins.put( - upgradePluginKey, - pad( - upgradePluginKey, - INFO_PAD_SIZE + getOutputLineWidthOffset(), - effectiveVersion, - " -> ", - newer)); + return Pair.of(finalEffectiveVersion, newer); } - } + }); minRequires = pluginRequires; } } catch (ArtifactResolutionException | ProjectBuildingException e) { @@ -734,7 +808,7 @@ private Map getParentsPlugins(List parents) throws map.keySet().retainAll(withVersionSpecified); parentPlugins.putAll(map); - map = getBuildPlugins(interpolatedModel, true); + map = getBuildPlugins(interpolatedModel); map.keySet().retainAll(withVersionSpecified); parentPlugins.putAll(map); @@ -747,7 +821,7 @@ private Map getParentsPlugins(List parents) throws } } else { parentPlugins.putAll(getPluginManagement(interpolatedModel)); - parentPlugins.putAll(getBuildPlugins(interpolatedModel, true)); + parentPlugins.putAll(getBuildPlugins(interpolatedModel)); parentPlugins.putAll(getReportPlugins(interpolatedModel, true)); } } @@ -759,7 +833,7 @@ private boolean isMavenPluginProject() { } private String compactKey(String groupId, String artifactId) { - return PomHelper.APACHE_MAVEN_PLUGINS_GROUPID.equals(groupId) + return APACHE_MAVEN_PLUGINS_GROUPID.equals(groupId) // a core plugin... group id is not needed ? artifactId : groupId + ":" + artifactId; @@ -824,7 +898,7 @@ private Set findPluginsWithVersionsSpecified(MutableXMLStreamReader pom) && PATTERN_PROJECT_PLUGIN.matcher(curState.path).matches()) { if (curState.artifactId != null && curState.version != null) { if (curState.groupId == null) { - curState.groupId = PomHelper.APACHE_MAVEN_PLUGINS_GROUPID; + curState.groupId = APACHE_MAVEN_PLUGINS_GROUPID; } result.add(curState.groupId + ":" + curState.artifactId); } @@ -857,16 +931,14 @@ private ArtifactVersion getPrerequisitesMavenVersion(MavenProject pluginProject) /** * Retrieves plugins from the given model * - * @param build build - * @param onlyIncludeInherited {@code true} to only return the plugins definitions that will be inherited by - * child projects. + * @param build build * @return map of plugin name x version */ - private Map getPluginsFromBuild(BuildBase build, boolean onlyIncludeInherited) { + private Map getPluginsFromBuild(BuildBase build) { return ofNullable(build) .flatMap(b -> ofNullable(b.getPlugins()).map(plugins -> plugins.stream() .filter(plugin -> plugin.getVersion() != null) - .filter(plugin -> !onlyIncludeInherited || getPluginInherited(plugin)) + .filter(DisplayPluginUpdatesMojo::getPluginInherited) .collect(toMap(Plugin::getKey, Plugin::getVersion)))) .orElse(emptyMap()); } @@ -874,16 +946,14 @@ private Map getPluginsFromBuild(BuildBase build, boolean onlyInc /** * Gets the build plugins of a specific project. * - * @param model the model to get the build plugins from. - * @param onlyIncludeInherited {@code true} to only return the plugins definitions that will be inherited by - * child projects. + * @param model the model to get the build plugins from. * @return The map of effective plugin versions keyed by coordinates. * @since 1.0-alpha-1 */ - private Map getBuildPlugins(Model model, boolean onlyIncludeInherited) { - Map buildPlugins = new HashMap<>(getPluginsFromBuild(model.getBuild(), onlyIncludeInherited)); + private Map getBuildPlugins(Model model) { + Map buildPlugins = new HashMap<>(getPluginsFromBuild(model.getBuild())); ofNullable(model.getProfiles()).ifPresent(profiles -> profiles.stream() - .map(profile -> getPluginsFromBuild(profile.getBuild(), onlyIncludeInherited)) + .map(profile -> getPluginsFromBuild(profile.getBuild())) .forEach(buildPlugins::putAll)); return buildPlugins; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java index ee89448620..ff59db68f7 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java @@ -21,7 +21,9 @@ import javax.inject.Inject; +import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; @@ -35,11 +37,16 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; +import org.codehaus.mojo.versions.api.ArtifactAssociation; import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.PropertyVersions; import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; @@ -157,7 +164,7 @@ public class DisplayPropertyUpdatesMojo extends AbstractVersionsDisplayMojo { * @param artifactFactory an {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -165,9 +172,9 @@ public DisplayPropertyUpdatesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -179,6 +186,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { logInit(); List current = new ArrayList<>(); List updates = new ArrayList<>(); + VersionChangeRecorder changeRecorder = getChangeRecorder(); Map propertyVersions = this.getHelper() .getVersionPropertiesMap(VersionsHelper.VersionPropertiesMapRequest.builder() @@ -207,18 +215,17 @@ public void execute() throws MojoExecutionException, MojoFailureException { log.info("Assuming allowMajorUpdates false because allowMinorUpdates is false."); } - Optional unchangedSegment1 = allowMajorUpdates && allowMinorUpdates && allowIncrementalUpdates + Optional unchangedSegment = allowMajorUpdates && allowMinorUpdates && allowIncrementalUpdates ? empty() : allowMinorUpdates && allowIncrementalUpdates ? of(MAJOR) : allowIncrementalUpdates ? of(MINOR) : of(INCREMENTAL); if (log != null && log.isDebugEnabled()) { - log.debug(unchangedSegment1 + log.debug(unchangedSegment .map(Segment::minorTo) .map(Segment::toString) .orElse("ALL") + " version changes allowed"); } - Optional unchangedSegment = unchangedSegment1; try { ArtifactVersion winner = version.getNewestVersion( currentVersion, property, this.allowSnapshots, this.reactorProjects, false, unchangedSegment); @@ -241,6 +248,19 @@ public void execute() throws MojoExecutionException, MojoFailureException { buf.append(" -> "); buf.append(newVersion); updates.add(buf.toString()); + + changeRecorder.recordChange(new PropertyVersionChange() + .withProperty(property.getName()) + .withOldValue(currentVersion) + .withNewValue(newVersion)); + Arrays.stream(version.getAssociations()) + .map(ArtifactAssociation::getArtifact) + .forEachOrdered(a -> changeRecorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROPERTY_UPDATE) + .withGroupId(a.getGroupId()) + .withArtifactId(a.getArtifactId()) + .withOldVersion(currentVersion) + .withNewVersion(newVersion))); } else { StringBuilder buf = new StringBuilder(); buf.append("${"); @@ -281,6 +301,11 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } logLine(false, ""); + try { + saveChangeRecorderResults(); + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage()); + } } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java index 03229289c6..87c9a10dd1 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java @@ -19,7 +19,9 @@ import javax.xml.stream.XMLStreamException; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -36,13 +38,17 @@ import org.codehaus.mojo.versions.api.ArtifactVersions; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; import static java.util.Collections.singletonList; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PARENT_UPDATE; /** * Replaces any -SNAPSHOT versions with a release version, older if necessary (if there has been a release). @@ -92,7 +98,7 @@ public class ForceReleasesMojo extends AbstractVersionsDependencyUpdaterMojo { * @param artifactFactory an {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -100,9 +106,9 @@ public ForceReleasesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -134,33 +140,34 @@ protected boolean getAllowSnapshots() { */ protected void update(MutableXMLStreamReader pom) throws MojoExecutionException, MojoFailureException, XMLStreamException, VersionRetrievalException { - try { - if (getProcessDependencyManagement()) { + List versionChanges = new ArrayList<>(); + if (getProcessDependencyManagement()) { + try { DependencyManagement dependencyManagement = PomHelper.getRawModel(getProject()).getDependencyManagement(); if (dependencyManagement != null) { - useReleases( - pom, - dependencyManagement.getDependencies(), - DependencyChangeRecord.ChangeKind.DEPENDENCY_MANAGEMENT); + versionChanges.addAll(getReleaseVersionChanges( + pom, dependencyManagement.getDependencies(), DEPENDENCY_MANAGEMENT_UPDATE)); } + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); } - if (getProject().getDependencies() != null && getProcessDependencies()) { - useReleases(pom, getProject().getDependencies(), DependencyChangeRecord.ChangeKind.DEPENDENCY); - } - if (getProject().getParent() != null && getProcessParent()) { - useReleases(pom, singletonList(getParentDependency()), DependencyChangeRecord.ChangeKind.PARENT); - } - } catch (IOException e) { - throw new MojoExecutionException(e.getMessage(), e); + } + if (getProject().getDependencies() != null && getProcessDependencies()) { + versionChanges.addAll(getReleaseVersionChanges(pom, getProject().getDependencies(), DEPENDENCY_UPDATE)); + } + if (getProject().getParent() != null && getProcessParent()) { + versionChanges.addAll(getReleaseVersionChanges(pom, singletonList(getParentDependency()), PARENT_UPDATE)); + } + for (DependencyVersionChange change : versionChanges) { + updateDependencyVersion(getProject(), pom, change); } } - private void useReleases( - MutableXMLStreamReader pom, - Collection dependencies, - DependencyChangeRecord.ChangeKind changeKind) - throws XMLStreamException, MojoExecutionException, VersionRetrievalException { + private List getReleaseVersionChanges( + MutableXMLStreamReader pom, Collection dependencies, DependencyChangeKind dependencyChangeKind) + throws MojoExecutionException, VersionRetrievalException { + List versionChanges = new ArrayList<>(); for (Dependency dep : dependencies) { if (getExcludeReactor() && isProducedByReactor(dep)) { getLog().info("Ignoring reactor dependency: " + toString(dep)); @@ -183,7 +190,12 @@ private void useReleases( getLog().debug("Looking for a release of " + toString(dep)); ArtifactVersions versions = getHelper().lookupArtifactVersions(artifact, false); if (versions.containsVersion(releaseVersion)) { - updateDependencyVersion(getProject(), pom, dep, releaseVersion, changeKind); + versionChanges.add(new DependencyVersionChange() + .withKind(dependencyChangeKind) + .withGroupId(artifact.getGroupId()) + .withArtifactId(artifact.getArtifactId()) + .withOldVersion(artifact.getVersion()) + .withNewVersion(releaseVersion)); } else { ArtifactVersion newestRelease = versions.getNewestVersion((VersionRange) null, null, false, true); if (newestRelease == null) { @@ -193,10 +205,16 @@ private void useReleases( "No matching release of " + toString(dep) + " found for update."); } } else { - updateDependencyVersion(getProject(), pom, dep, newestRelease.toString(), changeKind); + versionChanges.add(new DependencyVersionChange() + .withKind(dependencyChangeKind) + .withGroupId(artifact.getGroupId()) + .withArtifactId(artifact.getArtifactId()) + .withOldVersion(artifact.getVersion()) + .withNewVersion(newestRelease.toString())); } } } } + return versionChanges; } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java index 057392bc2b..037a59e4be 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java @@ -41,7 +41,7 @@ import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -100,7 +100,7 @@ public class LockSnapshotsMojo extends AbstractVersionsDependencyUpdaterMojo { * @param artifactFactory an {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -108,9 +108,9 @@ public LockSnapshotsMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java index 7a5b68cdfe..d106792460 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java @@ -46,7 +46,7 @@ import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; @@ -168,7 +168,7 @@ public class ResolveRangesMojo extends AbstractVersionsDependencyUpdaterMojo { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -176,9 +176,9 @@ public ResolveRangesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java index 6054ff8f0e..3008c6fb2d 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java @@ -22,10 +22,9 @@ import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -48,10 +47,10 @@ import org.apache.maven.project.ProjectBuilder; import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; -import org.codehaus.mojo.versions.change.VersionChanger; -import org.codehaus.mojo.versions.change.VersionChangerFactory; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.ordering.ReactorDepthComparator; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; @@ -65,7 +64,7 @@ import static org.apache.commons.lang3.StringUtils.isEmpty; /** - * Sets the current project's version and based on that change propagates that change onto any child modules as + * Sets the current project's version and based on that change propagataes that change onto any child modules as * necessary. * * @author Stephen Connolly @@ -253,9 +252,9 @@ public class SetMojo extends AbstractVersionsUpdaterMojo { protected boolean allowSnapshots; /** - * The changes to module coordinates. Guarded by this. + * Dependencies to be checked/updated stored as DependencyVersionChange entities with {@code null} kind */ - private final transient List sourceChanges = new ArrayList<>(); + private final Set sourceChanges = new HashSet<>(); /** * The (injected) instance of {@link ProjectBuilder} @@ -271,7 +270,7 @@ public class SetMojo extends AbstractVersionsUpdaterMojo { * @param repositorySystem the repository system * @param projectBuilder the project builder * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @param prompter the prompter * @throws MojoExecutionException when things go wrong */ @@ -281,10 +280,10 @@ public SetMojo( RepositorySystem repositorySystem, ProjectBuilder projectBuilder, Map wagonMap, - Map changeRecorders, + Map changeRecorderFactories, Prompter prompter) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); this.projectBuilder = projectBuilder; this.prompter = prompter; } @@ -294,12 +293,6 @@ protected boolean getAllowSnapshots() { return allowSnapshots; } - private synchronized void addChange(String groupId, String artifactId, String oldVersion, String newVersion) { - if (!newVersion.equals(oldVersion)) { - sourceChanges.add(new DefaultDependencyVersionChange(groupId, artifactId, oldVersion, newVersion)); - } - } - /** * Called when this mojo is executed. * @@ -501,7 +494,11 @@ private void applyChange( getLog().debug("Applying change " + groupId + ":" + artifactId + ":" + oldVersion + " -> " + newVersion); // this is a triggering change - addChange(groupId, artifactId, oldVersion, newVersion); + sourceChanges.add(new DependencyVersionChange() + .withGroupId(groupId) + .withArtifactId(artifactId) + .withOldVersion(oldVersion) + .withNewVersion(newVersion)); // now fake out the triggering change Map.Entry current = PomHelper.getModelEntry(reactor, groupId, artifactId); @@ -577,11 +574,12 @@ private void applyChange( + ArtifactUtils.versionlessKey( PomHelper.getGroupId(targetModel), PomHelper.getArtifactId(targetModel)) + ":" + sourceVersion); - addChange( - PomHelper.getGroupId(targetModel), - PomHelper.getArtifactId(targetModel), - PomHelper.getVersion(targetModel), - sourceVersion); + sourceChanges.add(new DependencyVersionChange() + .withGroupId(PomHelper.getGroupId(targetModel)) + .withArtifactId(PomHelper.getArtifactId(targetModel)) + .withOldVersion(PomHelper.getVersion(targetModel)) + .withNewVersion(sourceVersion)); + targetModel.setVersion(sourceVersion); } else { getLog().debug(" module is " @@ -610,16 +608,20 @@ protected synchronized void update(MutableXMLStreamReader pom) PomHelper.getRawModel(pom.getSource(), pom.getFileName().toFile()); log.setContext("Processing " + PomHelper.getGroupId(model) + ":" + PomHelper.getArtifactId(model)); - VersionChangerFactory versionChangerFactory = new VersionChangerFactory(); - versionChangerFactory.setPom(pom); - versionChangerFactory.setLog(log); - versionChangerFactory.setModel(model); - - VersionChanger changer = versionChangerFactory.newVersionChanger( - processParent, processProject, processDependencies, processPlugins); - - for (DefaultDependencyVersionChange versionChange : sourceChanges) { - changer.apply(versionChange); + VersionChangeRecorder changeRecorder = getChangeRecorder(); + for (DependencyVersionChange versionChange : sourceChanges) { + if (processParent) { + processParent(pom, model, versionChange, changeRecorder); + } + if (processProject) { + processProject(pom, model, versionChange, changeRecorder); + } + if (processDependencies) { + processDependency(pom, model, versionChange, changeRecorder); + } + if (processPlugins) { + processPlugin(pom, versionChange, changeRecorder); + } } if (updateBuildOutputTimestamp && !"never".equals(updateBuildOutputTimestampPolicy)) { @@ -634,6 +636,103 @@ protected synchronized void update(MutableXMLStreamReader pom) log.clearContext(); } + private void processParent( + MutableXMLStreamReader pom, + Model model, + DependencyVersionChange versionChange, + VersionChangeRecorder changeRecorder) + throws XMLStreamException { + if (model.getParent() != null + && versionChange.getGroupId().equals(model.getParent().getGroupId()) + && versionChange.getArtifactId().equals(model.getParent().getArtifactId())) { + if (PomHelper.setProjectParentVersion(pom, versionChange.getNewVersion())) { + getLog().info(" Updating parent " + versionChange.getGroupId() + ":" + + versionChange.getArtifactId()); + getLog().info(" from version " + versionChange.getOldVersion() + " to " + + versionChange.getNewVersion()); + changeRecorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId(versionChange.getGroupId()) + .withArtifactId(versionChange.getArtifactId()) + .withOldVersion(versionChange.getOldVersion()) + .withNewVersion(versionChange.getNewVersion())); + } + } else { + getLog().warn("Not processing parent: there is no parent."); + } + } + + private void processProject( + MutableXMLStreamReader pom, + Model model, + DependencyVersionChange versionChange, + VersionChangeRecorder changeRecorder) + throws XMLStreamException { + if (versionChange.getGroupId().equals(PomHelper.getGroupId(model)) + && versionChange.getArtifactId().equals(PomHelper.getArtifactId(model))) { + if (PomHelper.setProjectVersion(pom, versionChange.getNewVersion())) { + getLog().info(" Updating project " + versionChange.getGroupId() + ":" + + versionChange.getArtifactId()); + getLog().info(" from version " + versionChange.getOldVersion() + " to " + + versionChange.getNewVersion()); + changeRecorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROJECT_UPDATE) + .withGroupId(versionChange.getGroupId()) + .withArtifactId(versionChange.getArtifactId()) + .withOldVersion(versionChange.getOldVersion()) + .withNewVersion(versionChange.getNewVersion())); + } + } + } + + private void processDependency( + MutableXMLStreamReader pom, + Model model, + DependencyVersionChange versionChange, + VersionChangeRecorder changeRecorder) + throws XMLStreamException { + if (PomHelper.setDependencyVersion( + pom, + versionChange.getGroupId(), + versionChange.getArtifactId(), + versionChange.getOldVersion(), + versionChange.getNewVersion(), + model, + getLog())) { + getLog().info(" Updating dependency " + versionChange.getGroupId() + ":" + + versionChange.getArtifactId()); + getLog().info(" from version " + versionChange.getOldVersion() + " to " + + versionChange.getNewVersion()); + changeRecorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId(versionChange.getGroupId()) + .withArtifactId(versionChange.getArtifactId()) + .withOldVersion(versionChange.getOldVersion()) + .withNewVersion(versionChange.getNewVersion())); + } + } + + private void processPlugin( + MutableXMLStreamReader pom, DependencyVersionChange versionChange, VersionChangeRecorder changeRecorder) + throws XMLStreamException { + if (PomHelper.setPluginVersion( + pom, + versionChange.getGroupId(), + versionChange.getArtifactId(), + versionChange.getOldVersion(), + versionChange.getNewVersion())) { + getLog().info(" Updating plugin " + versionChange.getGroupId() + ":" + versionChange.getArtifactId()); + getLog().info(" from version " + versionChange.getOldVersion() + " to " + + versionChange.getNewVersion()); + changeRecorder.recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.PLUGIN_UPDATE) + .withGroupId(versionChange.getGroupId()) + .withArtifactId(versionChange.getArtifactId()) + .withOldVersion(versionChange.getOldVersion()) + .withNewVersion(versionChange.getNewVersion())); + } + } + private void updateBuildOutputTimestamp(MutableXMLStreamReader pom, Model model) throws XMLStreamException { String buildOutputTimestamp = model.getProperties().getProperty("project.build.outputTimestamp"); diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java index 8561918291..807d071c3e 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java @@ -37,7 +37,7 @@ import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.PropertyVersions; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.PropertiesVersionsFileReader; @@ -112,7 +112,7 @@ public class SetPropertyMojo extends AbstractVersionsUpdaterMojo { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -120,9 +120,9 @@ public SetPropertyMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java index 423bcf0cb9..8014cea004 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java @@ -17,7 +17,7 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -80,7 +80,7 @@ public class SetScmTagMojo extends AbstractVersionsUpdaterMojo { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -88,9 +88,9 @@ public SetScmTagMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java index 43b5caedd7..bd5e5b0525 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java @@ -34,13 +34,17 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.codehaus.mojo.versions.recording.DefaultDependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PARENT_UPDATE; + /** * Attempts to resolve unlocked snapshot dependency versions to the locked timestamp versions used in the build. For * example, an unlocked snapshot version like "1.0-SNAPSHOT" could be resolved to "1.0-20090128.202731-1". If a @@ -92,7 +96,7 @@ public class UnlockSnapshotsMojo extends AbstractVersionsDependencyUpdaterMojo { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -100,9 +104,9 @@ public UnlockSnapshotsMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -137,17 +141,15 @@ protected void update(MutableXMLStreamReader pom) throws MojoExecutionException, MojoFailureException, XMLStreamException { try { if (getProcessDependencyManagement()) { + // TODO: Perhaps we can use original model instead? DependencyManagement dependencyManagement = PomHelper.getRawModel(getProject()).getDependencyManagement(); if (dependencyManagement != null) { - unlockSnapshots( - pom, - dependencyManagement.getDependencies(), - DependencyChangeRecord.ChangeKind.DEPENDENCY_MANAGEMENT); + unlockSnapshots(pom, dependencyManagement.getDependencies(), DEPENDENCY_MANAGEMENT_UPDATE); } } if (getProject().getDependencies() != null && getProcessDependencies()) { - unlockSnapshots(pom, getProject().getDependencies(), DependencyChangeRecord.ChangeKind.DEPENDENCY); + unlockSnapshots(pom, getProject().getDependencies(), DEPENDENCY_UPDATE); } if (getProject().getParent() != null && getProcessParent()) { unlockParentSnapshot(pom, getProject().getParent()); @@ -158,7 +160,7 @@ protected void update(MutableXMLStreamReader pom) } private void unlockSnapshots( - MutableXMLStreamReader pom, List dependencies, DependencyChangeRecord.ChangeKind changeKind) + MutableXMLStreamReader pom, List dependencies, DependencyChangeKind changeKind) throws XMLStreamException, MojoExecutionException { for (Dependency dep : dependencies) { if (getExcludeReactor() && isProducedByReactor(dep)) { @@ -189,11 +191,12 @@ private void unlockSnapshots( getLog())) { getChangeRecorder() - .recordChange(DefaultDependencyChangeRecord.builder() + .recordChange(new DependencyVersionChange() .withKind(changeKind) - .withDependency(dep) - .withNewVersion(unlockedVersion) - .build()); + .withGroupId(dep.getGroupId()) + .withArtifactId(dep.getArtifactId()) + .withOldVersion(dep.getVersion()) + .withNewVersion(unlockedVersion)); getLog().info("Unlocked " + toString(dep) + " to version " + unlockedVersion); } } @@ -221,11 +224,12 @@ private void unlockParentSnapshot(MutableXMLStreamReader pom, MavenProject paren if (PomHelper.setProjectParentVersion(pom, unlockedParentVersion)) { getLog().info("Unlocked parent " + parentArtifact + " to version " + unlockedParentVersion); getChangeRecorder() - .recordChange(DefaultDependencyChangeRecord.builder() - .withKind(DependencyChangeRecord.ChangeKind.PARENT) - .withArtifact(parentArtifact) - .withNewVersion(unlockedParentVersion) - .build()); + .recordChange(new DependencyVersionChange() + .withKind(PARENT_UPDATE) + .withGroupId(parentArtifact.getGroupId()) + .withArtifactId(parentArtifact.getArtifactId()) + .withOldVersion(parentVersion) + .withNewVersion(unlockedParentVersion)); } } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java index ae949d3149..11fd301c01 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java @@ -38,7 +38,7 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -81,7 +81,7 @@ public class UpdateChildModulesMojo extends AbstractVersionsUpdaterMojo { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -89,9 +89,9 @@ public UpdateChildModulesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java index a03d32b3bc..2e8d8a7e36 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java @@ -38,9 +38,9 @@ import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.codehaus.mojo.versions.recording.DefaultDependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; @@ -147,7 +147,7 @@ public class UpdateParentMojo extends UseLatestVersionsMojoBase { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -155,9 +155,9 @@ public UpdateParentMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -263,13 +263,12 @@ protected void update(MutableXMLStreamReader pom) + getProject().getParent().getVersion() + " to " + parentVersion); } getChangeRecorder() - .recordChange(DefaultDependencyChangeRecord.builder() - .withKind(DependencyChangeRecord.ChangeKind.PARENT) + .recordChange(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) .withGroupId(getProject().getParent().getGroupId()) .withArtifactId(getProject().getParent().getArtifactId()) .withOldVersion(getProject().getParent().getVersion()) - .withNewVersion(parentVersion) - .build()); + .withNewVersion(parentVersion)); } } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java index bdc96f971c..58e601d0a2 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java @@ -32,7 +32,7 @@ import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.VersionsHelper; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -98,7 +98,7 @@ public class UpdatePropertiesMojo extends UpdatePropertiesMojoBase { * @param artifactFactory an {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -106,9 +106,9 @@ public UpdatePropertiesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java index ecabf70cfe..b96a44b30e 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java @@ -30,11 +30,10 @@ import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.PropertyVersions; import org.codehaus.mojo.versions.api.Segment; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; -import org.codehaus.mojo.versions.recording.DefaultDependencyChangeRecord; -import org.codehaus.mojo.versions.recording.DefaultPropertyChangeRecord; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -44,6 +43,7 @@ import static org.codehaus.mojo.versions.api.Segment.INCREMENTAL; import static org.codehaus.mojo.versions.api.Segment.MAJOR; import static org.codehaus.mojo.versions.api.Segment.MINOR; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PROPERTY_UPDATE; /** * Common base class for {@link UpdatePropertiesMojo} @@ -145,16 +145,16 @@ public abstract class UpdatePropertiesMojoBase extends AbstractVersionsDependenc * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ public UpdatePropertiesMojoBase( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -205,25 +205,26 @@ protected void update(MutableXMLStreamReader pom, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java index 9e6d512f29..1d87acdee6 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java @@ -52,9 +52,10 @@ import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord.ChangeKind; -import org.codehaus.mojo.versions.recording.DefaultPropertyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyComparator; @@ -65,6 +66,9 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static java.util.Optional.ofNullable; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PARENT_UPDATE; /** * Updates a dependency to a specific version. @@ -163,7 +167,7 @@ protected boolean getAllowSnapshots() { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -171,9 +175,9 @@ public UseDepVersionMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override @@ -287,7 +291,7 @@ protected void processModel( project, node, node.getModel().getDependencyManagement().getDependencies(), - ChangeKind.DEPENDENCY_MANAGEMENT, + DEPENDENCY_MANAGEMENT_UPDATE, propertyBacklog, propertyConflicts); } @@ -297,7 +301,7 @@ protected void processModel( project, node, getDependencies(node.getModel()), - ChangeKind.DEPENDENCY, + DEPENDENCY_UPDATE, propertyBacklog, propertyConflicts); } @@ -307,7 +311,7 @@ protected void processModel( project, node, singletonList(getParentDependency()), - ChangeKind.PARENT, + PARENT_UPDATE, propertyBacklog, propertyConflicts); } @@ -398,7 +402,6 @@ private static List getDependencies(Model model) { * @param node model tree node to process * @param dependencies collection of dependencies to process (can be taken from dependency management, * parent, or dependencies) - * @param changeKind {@link ChangeKind} instance for the change recorder * @param propertyBacklog a {@link Set} instance used to store dependencies to be updated, but which were not found * in the current subtree. These properties need to be carried over to the parent node for * processing. @@ -414,20 +417,14 @@ private void useDepVersion( MavenProject project, ModelNode node, Collection dependencies, - ChangeKind changeKind, + DependencyChangeKind changeKind, Set propertyBacklog, Map> propertyConflicts) throws MojoExecutionException, XMLStreamException, VersionRetrievalException { // an additional pass is necessary to collect conflicts if processProperties is enabled if (processProperties) { dependencies.stream() - .filter(dep -> { - try { - return !isIncluded(toArtifact(dep)); - } catch (MojoExecutionException e) { - throw new RuntimeException(e); - } - }) + .filter(dep -> !isIncluded(toArtifact(dep))) .forEach(dep -> // if a dependency that is _not_ to be changed is set using a property, register that // property @@ -474,7 +471,15 @@ private void useDepVersion( } } if (!propertyName.isPresent()) { - updateDependencyVersion(project, node.getMutableXMLStreamReader(), dep, depVersion, changeKind); + updateDependencyVersion( + project, + node.getMutableXMLStreamReader(), + new DependencyVersionChange() + .withKind(changeKind) + .withGroupId(dep.getGroupId()) + .withArtifactId(dep.getArtifactId()) + .withOldVersion(dep.getVersion()) + .withNewVersion(depVersion)); } else { // propertyName is present ofNullable(propertyConflicts.get(propertyName.get())) @@ -536,16 +541,11 @@ private boolean updatePropertyValue(ModelNode node, String property) { property, depVersion); if (result) { - try { - getChangeRecorder() - .recordChange(DefaultPropertyChangeRecord.builder() - .withProperty(property) - .withOldValue(pair.getRight()) - .withNewValue(depVersion) - .build()); - } catch (MojoExecutionException e) { - throw new RuntimeException(e); - } + getChangeRecorder() + .recordChange(new PropertyVersionChange() + .withProperty(property) + .withOldValue(pair.getRight()) + .withNewValue(depVersion)); } return result; } catch (XMLStreamException e) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java index 57bc938551..98d26fdfba 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java @@ -29,7 +29,7 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -118,7 +118,7 @@ public class UseLatestReleasesMojo extends UseLatestVersionsMojoBase { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -126,9 +126,9 @@ public UseLatestReleasesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java index 4a381c0a94..9f0b026970 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java @@ -29,7 +29,7 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -101,7 +101,7 @@ public class UseLatestSnapshotsMojo extends UseLatestVersionsMojoBase { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -109,9 +109,9 @@ public UseLatestSnapshotsMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java index f02b538ad9..bc86fae776 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java @@ -29,7 +29,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.AbstractVersionDetails; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -132,7 +132,7 @@ protected boolean getAllowSnapshots() { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -140,9 +140,9 @@ public UseLatestVersionsMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java index 0bca152e4a..524cd2cc35 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java @@ -42,8 +42,9 @@ import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; @@ -52,6 +53,9 @@ import org.eclipse.aether.RepositorySystem; import static java.util.Collections.singletonList; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PARENT_UPDATE; /** * Common base class for {@link UseLatestVersionsMojo} @@ -128,77 +132,16 @@ public abstract class UseLatestVersionsMojoBase extends AbstractVersionsDependen * @param artifactFactory an {@link ArtifactFactory} instance * @param repositorySystem a {@link RepositorySystem} instance * @param wagonMap a map of wagon providers per protocol - * @param changeRecorders a map of change recorders + * @param changeRecorderFactories a map of change recorder factories * @throws MojoExecutionException when things go wrong */ public UseLatestVersionsMojoBase( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); - } - - /** - * Represents a version change of an artifact - */ - private abstract static class ArtifactVersionChange { - private final DependencyChangeRecord.ChangeKind changeKind; - - private final String newVersion; - - /** - * Creates a new instance - * - * @param changeKind change kind - * @param newVersion new version - */ - ArtifactVersionChange(DependencyChangeRecord.ChangeKind changeKind, String newVersion) { - this.changeKind = changeKind; - this.newVersion = newVersion; - } - - /** - * @return change kind - */ - DependencyChangeRecord.ChangeKind getChangeKind() { - return changeKind; - } - - /** - * @return new version - */ - String getNewVersion() { - return newVersion; - } - } - - /** - * Represents a version change of a dependency - */ - private static final class DependencyVersionChange extends ArtifactVersionChange { - private final Dependency dependency; - - /** - * Constructs a new instance - * - * @param changeKind change kind - * @param dependency {@code Dependency} instance - * @param newVersion new version - */ - DependencyVersionChange( - DependencyChangeRecord.ChangeKind changeKind, Dependency dependency, String newVersion) { - super(changeKind, newVersion); - this.dependency = dependency; - } - - /** - * @return {@code Dependency} instance - */ - Dependency getDependency() { - return dependency; - } + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } /** @@ -226,30 +169,23 @@ protected void update(MutableXMLStreamReader pom) versionChangeFutures.add(getUpdates( versionChanges, dependencyManagement.getDependencies(), - DependencyChangeRecord.ChangeKind.DEPENDENCY_MANAGEMENT, + DEPENDENCY_MANAGEMENT_UPDATE, unchangedSegment)); } } if (getProject().getDependencies() != null && getProcessDependencies()) { versionChangeFutures.add(getUpdates( - versionChanges, - getProject().getDependencies(), - DependencyChangeRecord.ChangeKind.DEPENDENCY, - unchangedSegment)); + versionChanges, getProject().getDependencies(), DEPENDENCY_UPDATE, unchangedSegment)); } if (getProject().getParent() != null && getProcessParent()) { versionChangeFutures.add(getUpdates( - versionChanges, - singletonList(getParentDependency()), - DependencyChangeRecord.ChangeKind.PARENT, - unchangedSegment)); + versionChanges, singletonList(getParentDependency()), PARENT_UPDATE, unchangedSegment)); } CompletableFuture.allOf(versionChangeFutures.toArray(new CompletableFuture[0])) .join(); for (DependencyVersionChange change : versionChanges) { - updateDependencyVersion( - getProject(), pom, change.getDependency(), change.getNewVersion(), change.getChangeKind()); + updateDependencyVersion(getProject(), pom, change); } } catch (IOException e) { throw new MojoExecutionException(e.getMessage(), e); @@ -270,7 +206,7 @@ protected void update(MutableXMLStreamReader pom) private CompletableFuture getUpdates( ConcurrentLinkedQueue updates, Collection dependencies, - DependencyChangeRecord.ChangeKind changeKind, + DependencyChangeKind kind, Optional unchangedSegment) { return CompletableFuture.allOf(dependencies.stream() .map(dep -> CompletableFuture.runAsync( @@ -300,8 +236,13 @@ private CompletableFuture getUpdates( getAllowSnapshots(), getAllowDowngrade())) .filter(this::artifactVersionsFilter)) - .ifPresent(ver -> updates.add( - new DependencyVersionChange(changeKind, dep, ver.toString()))); + .map(ver -> new DependencyVersionChange() + .withKind(kind) + .withGroupId(dep.getGroupId()) + .withArtifactId(dep.getArtifactId()) + .withOldVersion(dep.getVersion()) + .withNewVersion(ver.toString())) + .ifPresent(updates::add); } catch (VersionRetrievalException | InvalidSegmentException | MojoExecutionException e) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java index 9ad6e0ce75..c191ef8b58 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java @@ -28,7 +28,7 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -81,7 +81,7 @@ public class UseNextReleasesMojo extends UseLatestVersionsMojoBase { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the wagon map - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException if any */ @Inject @@ -89,9 +89,9 @@ public UseNextReleasesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java index d287907426..e1767223de 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java @@ -28,7 +28,7 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -100,7 +100,7 @@ public class UseNextSnapshotsMojo extends UseLatestVersionsMojoBase { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -108,9 +108,9 @@ public UseNextSnapshotsMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java index d25b8dd7df..673e5af693 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java @@ -27,7 +27,7 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -95,7 +95,7 @@ protected boolean getAllowSnapshots() { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -103,9 +103,9 @@ public UseNextVersionsMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } @Override diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java index 561d97b7b2..20a729fa76 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java @@ -25,8 +25,8 @@ import java.io.IOException; import java.util.Collection; import java.util.Map; +import java.util.Objects; -import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.model.DependencyManagement; @@ -38,9 +38,10 @@ import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; +import org.codehaus.mojo.versions.utils.VersionStringComparator; import org.eclipse.aether.RepositorySystem; /** @@ -112,7 +113,7 @@ protected boolean getAllowSnapshots() { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -120,9 +121,9 @@ public UseReactorMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } /** @@ -153,8 +154,7 @@ protected void update(MutableXMLStreamReader pom) } } - private void useReactor(MutableXMLStreamReader pom, Collection dependencies) - throws XMLStreamException, MojoExecutionException, VersionRetrievalException { + private void useReactor(MutableXMLStreamReader pom, Collection dependencies) throws XMLStreamException { for (Dependency dep : dependencies) { Artifact artifact = this.toArtifact(dep); @@ -163,9 +163,9 @@ private void useReactor(MutableXMLStreamReader pom, Collection depen } for (MavenProject reactorProject : reactorProjects) { - if (StringUtils.equals(reactorProject.getGroupId(), dep.getGroupId()) - && StringUtils.equals(reactorProject.getArtifactId(), dep.getArtifactId()) - && !StringUtils.equals(reactorProject.getVersion(), dep.getVersion())) { + if (Objects.equals(reactorProject.getGroupId(), dep.getGroupId()) + && Objects.equals(reactorProject.getArtifactId(), dep.getArtifactId()) + && VersionStringComparator.STRICT.compare(reactorProject.getVersion(), dep.getVersion()) != 0) { if (PomHelper.setDependencyVersion( pom, dep.getGroupId(), @@ -182,12 +182,11 @@ private void useReactor(MutableXMLStreamReader pom, Collection depen } } - private void useReactor(MutableXMLStreamReader pom, MavenProject parent) - throws XMLStreamException, VersionRetrievalException { + private void useReactor(MutableXMLStreamReader pom, MavenProject parent) throws XMLStreamException { for (MavenProject project : reactorProjects) { - if (StringUtils.equals(project.getGroupId(), parent.getGroupId()) - && StringUtils.equals(project.getArtifactId(), parent.getArtifactId()) - && !StringUtils.equals(project.getVersion(), parent.getVersion())) { + if (Objects.equals(project.getGroupId(), parent.getGroupId()) + && Objects.equals(project.getArtifactId(), parent.getArtifactId()) + && VersionStringComparator.STRICT.compare(project.getVersion(), parent.getVersion()) != 0) { if (PomHelper.setProjectParentVersion(pom, project.getVersion())) { getLog().info("Updated parent " + toString(parent) + " to version " + project.getVersion()); } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java index f5fca39443..1e291c1c05 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java @@ -19,8 +19,10 @@ import javax.xml.stream.XMLStreamException; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.regex.Matcher; @@ -37,13 +39,17 @@ import org.codehaus.mojo.versions.api.ArtifactVersions; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; import static java.util.Collections.singletonList; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.DEPENDENCY_UPDATE; +import static org.codehaus.mojo.versions.model.DependencyChangeKind.PARENT_UPDATE; /** * Replaces any -SNAPSHOT versions with the corresponding release version (if it has been released). @@ -126,7 +132,7 @@ protected boolean getAllowSnapshots() { * @param artifactFactory the artifact factory * @param repositorySystem the repository system * @param wagonMap the map of wagon implementations - * @param changeRecorders the change recorders + * @param changeRecorderFactories the change recorder factories * @throws MojoExecutionException when things go wrong */ @Inject @@ -134,9 +140,9 @@ public UseReleasesMojo( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Map wagonMap, - Map changeRecorders) + Map changeRecorderFactories) throws MojoExecutionException { - super(artifactFactory, repositorySystem, wagonMap, changeRecorders); + super(artifactFactory, repositorySystem, wagonMap, changeRecorderFactories); } /** @@ -148,33 +154,34 @@ public UseReleasesMojo( */ protected void update(MutableXMLStreamReader pom) throws MojoExecutionException, MojoFailureException, XMLStreamException, VersionRetrievalException { - try { - if (getProcessDependencyManagement()) { + List versionChanges = new ArrayList<>(); + if (getProcessDependencyManagement()) { + try { DependencyManagement dependencyManagement = PomHelper.getRawModel(getProject()).getDependencyManagement(); if (dependencyManagement != null) { - useReleases( - pom, - dependencyManagement.getDependencies(), - DependencyChangeRecord.ChangeKind.DEPENDENCY_MANAGEMENT); + versionChanges.addAll(getReleaseVersionChanges( + dependencyManagement.getDependencies(), DEPENDENCY_MANAGEMENT_UPDATE)); } + } catch (IOException e) { + throw new MojoExecutionException(e.getMessage(), e); } - if (getProject().getDependencies() != null && getProcessDependencies()) { - useReleases(pom, getProject().getDependencies(), DependencyChangeRecord.ChangeKind.DEPENDENCY); - } - if (getProject().getParent() != null && getProcessParent()) { - useReleases(pom, singletonList(getParentDependency()), DependencyChangeRecord.ChangeKind.PARENT); - } - } catch (IOException e) { - throw new MojoExecutionException(e.getMessage(), e); + } + if (getProject().getDependencies() != null && getProcessDependencies()) { + versionChanges.addAll(getReleaseVersionChanges(getProject().getDependencies(), DEPENDENCY_UPDATE)); + } + if (getProject().getParent() != null && getProcessParent()) { + versionChanges.addAll(getReleaseVersionChanges(singletonList(getParentDependency()), PARENT_UPDATE)); + } + for (DependencyVersionChange change : versionChanges) { + updateDependencyVersion(getProject(), pom, change); } } - private void useReleases( - MutableXMLStreamReader pom, - Collection dependencies, - DependencyChangeRecord.ChangeKind changeKind) - throws XMLStreamException, MojoExecutionException, VersionRetrievalException { + private List getReleaseVersionChanges( + Collection dependencies, DependencyChangeKind dependencyChangeKind) + throws MojoExecutionException, VersionRetrievalException { + List versionChanges = new ArrayList<>(); for (Dependency dep : dependencies) { if (getExcludeReactor() && isProducedByReactor(dep)) { getLog().info("Ignoring reactor dependency: " + toString(dep)); @@ -194,7 +201,7 @@ private void useReleases( Matcher versionMatcher = SNAPSHOT_REGEX.matcher(version); if (versionMatcher.matches()) { String releaseVersion = versionMatcher.group(1); - Artifact artifact = this.toArtifact(dep); + Artifact artifact = toArtifact(dep); if (!isIncluded(artifact)) { continue; } @@ -205,8 +212,14 @@ private void useReleases( artifact.setVersion(releaseVersion); Optional targetVersion = findReleaseVersion(releaseVersion, getHelper().lookupArtifactVersions(artifact, false)); + if (targetVersion.isPresent()) { - updateDependencyVersion(getProject(), pom, dep, targetVersion.get(), changeKind); + versionChanges.add(new DependencyVersionChange() + .withKind(dependencyChangeKind) + .withGroupId(artifact.getGroupId()) + .withArtifactId(artifact.getArtifactId()) + .withOldVersion(version) + .withNewVersion(targetVersion.get())); } else { getLog().info("No matching release of " + toString(dep) + " to update."); if (failIfNotReplaced) { @@ -216,6 +229,8 @@ private void useReleases( } } } + + return versionChanges; } private Optional findReleaseVersion(String releaseVersion, ArtifactVersions versions) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java index c0034894ca..b4fde1995f 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java @@ -6,6 +6,7 @@ import java.util.Optional; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.function.TriFunction; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.Restriction; @@ -16,6 +17,7 @@ import org.codehaus.mojo.versions.DisplayExtensionUpdatesMojo; import org.codehaus.mojo.versions.api.ArtifactVersions; import org.codehaus.mojo.versions.api.Segment; +import org.codehaus.mojo.versions.model.VersionChange; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.rule.RuleService; import org.codehaus.mojo.versions.rule.RuleServiceUtils; @@ -97,11 +99,15 @@ private boolean dependencyVersionLocalToProject(Dependency dependency) { *

The resulting dependencies are filtered using the include/exclude rules from the {@link RuleService}.

* * @param updates map of available versions per dependency + * @param versionChangeProvider a producer of the {@link VersionChange} object for discovered updates per (dependency, old version and new version) * @return a {@link DependencyUpdatesResult} object containing the result */ - public DependencyUpdatesResult getDependencyUpdates(Map updates) { + public DependencyUpdatesResult getDependencyUpdates( + Map updates, + TriFunction versionChangeProvider) { List withUpdates = new ArrayList<>(); List usingCurrent = new ArrayList<>(); + List versionChanges = new ArrayList<>(); for (Map.Entry entry : updates.entrySet()) { Dependency dep = entry.getKey(); ArtifactVersions versions = RuleServiceUtils.filterByRuleService( @@ -145,7 +151,12 @@ public DependencyUpdatesResult getDependencyUpdates(Map currentVersion + " -> " + v).orElse(currentVersion); - List t = latestVersion.isPresent() ? withUpdates : usingCurrent; + List t = latestVersion + .map(v -> { + versionChanges.add(versionChangeProvider.apply(dep, currentVersion, v.toString())); + return withUpdates; + }) + .orElse(usingCurrent); if (right.length() + left.length() + 3 > maxLineWidth) { t.add(left + "..."); t.add(StringUtils.leftPad(right, maxLineWidth)); @@ -165,6 +176,11 @@ public List getUsingLatest() { public List getWithUpdates() { return withUpdates; } + + @Override + public List getVersionChanges() { + return versionChanges; + } }; } @@ -186,5 +202,13 @@ public interface DependencyUpdatesResult { * @return Dependencies with updates available */ List getWithUpdates(); + + /** + * Returns a list of {@link VersionChange} describing all registered version changes in the + * {@link org.codehaus.mojo.versions.api.recording.VersionChangeRecorder} comprehension + * + * @return a list of {@link VersionChange} objects describing the changes + */ + List getVersionChanges(); } } diff --git a/versions-maven-plugin/src/site/markdown/examples/recording-changes.md b/versions-maven-plugin/src/site/markdown/examples/recording-changes.md index 2cd0f3c6f2..85e7799cbc 100644 --- a/versions-maven-plugin/src/site/markdown/examples/recording-changes.md +++ b/versions-maven-plugin/src/site/markdown/examples/recording-changes.md @@ -21,13 +21,34 @@ under the License. # Recording Changes +Out of the box, the following recorders are provided: + +| Name | Description | +|------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| none | An "empty" recorder that will not output any changes | +| xml | A recorder writing to an XML file conforming to the legacy http://www.mojohaus.org/versions-maven-plugin/schema/updates/2.0 namespace, or to the http://www.mojohaus.org/versions-maven-plugin/schema/updates/3.0 namespace if`legacy=false` is provided as options | +| json | A recorder writing to a Json file | +| csv | A recorder writing to a CSV file | + +## Legacy XML format + +To generate a simple XML logs compatible with the legacy schema, use the following example: Here's an example: -```sh +```shell mvn versions:use-latest-releases -DchangeRecorderFormat=xml ``` -Which writes a file to `target/versions-changes.xml` that looks something like: +By default, the report will be written to `target/versions-changes.xml`. + +* If you'd rather that the file was written elsewhere, just use the additional `-DchangeRecorderOutputFileName` option, providing + the filename (without its path), like so: + + ```shell + mvn versions:use-latest-releases -DchangeRecorderFormat=xml -DchangeRecorderOutputFileName=changes.xml + ``` + +The result should be: ```xml @@ -45,3 +66,104 @@ Which writes a file to `target/versions-changes.xml` that looks something like: The contents of this file records the fact that `localhost:dummy-api:1.1.1-2` was upgraded to `3.0` and that the property `revision` changed its value from `3.0` to `3.1`. + +## New XML format + +The _legacy_ XML renderer does not allow appending to the change record once it's been written, so multiple executions of the plugin +will each overwrite the outcome of the previous execution. That's why there is now a new file format available. + +At the time being, the new file format can be activated by providing a change recorder option: + +```shell +mvn versions:use-latest-releases -DchangeRecorderFormat=xml -DchangeRecorderOptions=legacy=false +``` + +This will generate the following file: + +```xml + + + + + + + +``` + +As you can see, the new format features an aggregate type above the `updates` element; also, the `updates` element +now includes attributes providing the Maven goal as well as the date and time of the execution. + +## JSON + +To generate a report in Json, use the following command: + +```shell +mvn versions:use-latest-releases -DchangeRecorderFormat=json +``` + +This will generate the following file: + +Because the version changes array can contain different classes of updates, it features an additional discriminator +called `updateClass`; valid values are: `dependency`, `plugin`, `property`, `extension`. + +```json +{ + "updates": [ + { + "versionChanges": [ + { + "updateClass": "dependency", + "kind": "dependency-update", + "groupId": "localhost", + "artifactId": "dummy-api", + "oldVersion": "1.1.1-2", + "newVersion": "3.0" + }, + { + "updateClass": "property", + "property": "revision", + "oldValue": "1.1.1-2", + "newValue": "3.0" + } + ], + "goal": "use-latest-releases", + "date": "2025-10-03T07:05:38.437013556+02:00" + } + ] +} +``` + +## CSV + +To generate a report in a semicolon-separated CSV file, use the following command: + +```shell +mvn versions:use-latest-releases -DchangeRecorderFormat=csv +``` + +Due to the fact that every row needs to contain information modelling different classes of changes, the row definition +differs from the XSD model. + +Each row of the CSV document will consist of the following columns: + +| Column name | Description | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| execution | Randomly generated discriminator of the Maven execution (UUID); rows bearing the same UUID will belong to the same Maven execution | +| goal | Indicates the Maven goal that produced the report lines with the UUID above | +| updateClass | Indicates the overarching class of the update: one of:`dependency`, `plugin`, `property`, `extension` | +| kind | Only defined for depenendency class updates; indicates the section where the dependency updates took place. One of:`project-update`, `dependency-update`, `dependency-management-update`, `parent-update`, `plugin-update`, `plugin-management-update`, `property-update` | +| groupId | Contains the groupId of the artifact under change; unfilled for properties | +| artifactId | Contains the artifactId of the artifact under change; unfilled for properties | +| property | Contains the name of the property; only applicable for property updates | +| oldValue | Contains the old version or old property value | +| newValue | Contains the new version or new property value | +| minMavenVersion | Contains the minimum Maven version applicable for the update; only applicable for plugin updates | + +And the result will be: + +```csv +execution;goal;date;updateClass;kind;groupId;artifactId;property;oldValue;newValue;minMavenVersion +c0cbf50d-047a-483a-8046-6e5631f94365;use-latest-releases;2025-10-04T11:10:51.765+02:00;dependency;dependency-update;localhost;dummy-api;;1.1.1-2;3.0; +c0cbf50d-047a-483a-8046-6e5631f94365;use-latest-releases;2025-10-04T11:10:51.765+02:00;property;;;;revision;1.1.1-2;3.0; +``` + diff --git a/versions-maven-plugin/src/site/site.xml b/versions-maven-plugin/src/site/site.xml index 8ed31255a8..3f5585717f 100644 --- a/versions-maven-plugin/src/site/site.xml +++ b/versions-maven-plugin/src/site/site.xml @@ -27,6 +27,7 @@ + diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java index 3b874786f2..58924d7f89 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java @@ -18,6 +18,7 @@ import java.io.File; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -41,6 +42,7 @@ import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.CloseableTempFile; import org.codehaus.mojo.versions.utils.DependencyBuilder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.hamcrest.Matchers; import org.junit.Before; @@ -66,6 +68,8 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.MockitoAnnotations.openMocks; @@ -147,6 +151,10 @@ public void testRuleSetPresentAndWorking() throws Exception { } private MavenProject createProject() { + File baseDir = mock(File.class); + Path basePath = mock(Path.class); + doReturn(basePath).when(baseDir).toPath(); + doReturn(basePath).when(basePath).resolve(anyString()); return new MavenProject(new Model() { { setGroupId("default-group"); @@ -165,6 +173,12 @@ private MavenProject createProject() { }) { { setOriginalModel(getModel()); + getBuild().setDirectory("target"); + } + + @Override + public File getBasedir() { + return baseDir; } }; } @@ -182,7 +196,7 @@ public void testVersionsWithQualifiersNotConsideredAsMinorUpdates() throws Excep } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); allowMajorUpdates = false; @@ -219,7 +233,7 @@ public void testAllowMajorUpdatesFalse() throws Exception { } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); allowMajorUpdates = false; @@ -253,7 +267,7 @@ public void testAllowMinorUpdatesFalse() throws Exception { } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); allowMinorUpdates = false; @@ -288,7 +302,7 @@ public void testAllowIncrementalUpdatesFalse() throws Exception { } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); allowIncrementalUpdates = false; @@ -326,7 +340,7 @@ public void testVersionsWithQualifiersNotConsideredAsIncrementalUpdates() throws } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); allowMinorUpdates = false; @@ -424,7 +438,7 @@ public void testAllowSnapshots() throws Exception { } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); processDependencies = true; @@ -456,7 +470,7 @@ private void testAllowUpdatesFromLesserSegments(String availableVersion) throws } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); processDependencies = true; @@ -644,7 +658,7 @@ private void testOutputFileOverwrite(boolean overwrite) throws Exception { } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); processDependencies = true; @@ -714,7 +728,7 @@ public void testShouldOnlyShowUpdates() throws Exception { } }), null, - null) { + TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); allowMajorUpdates = true; diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java index 6c87b3c48b..55729cfda9 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java @@ -16,6 +16,7 @@ * limitations under the License. */ +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -36,6 +37,7 @@ import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.ExtensionBuilder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.junit.After; import org.junit.Before; @@ -59,6 +61,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.MockitoAnnotations.openMocks; @@ -87,7 +90,13 @@ public void setUp() throws IllegalAccessException, IOException, MojoExecutionExc openMocks(this); ArtifactHandlerManager artifactHandlerManager = mockArtifactHandlerManager(); artifactFactory = new ArtifactFactory(artifactHandlerManager); - mojo = new DisplayExtensionUpdatesMojo(artifactFactory, mockAetherRepositorySystem(), null, null); + mojo = new DisplayExtensionUpdatesMojo( + artifactFactory, mockAetherRepositorySystem(), null, TestVersionChangeRecorder.asTestMap()); + File baseDir = mock(File.class); + Path basePath = mock(Path.class); + doReturn(basePath).when(baseDir).toPath(); + doReturn(basePath).when(basePath).resolve(ArgumentMatchers.any()); + doReturn(basePath).when(basePath).resolve(ArgumentMatchers.any()); mojo.project = new MavenProject() { { setModel(new Model() { @@ -98,6 +107,11 @@ public void setUp() throws IllegalAccessException, IOException, MojoExecutionExc } }); } + + @Override + public File getBasedir() { + return baseDir; + } }; mojo.project.setRemoteArtifactRepositories(emptyList()); mojo.project.setPluginArtifactRepositories(emptyList()); diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java index 2e60b913e0..7fe2907964 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java @@ -17,6 +17,7 @@ import javax.xml.stream.XMLStreamException; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -41,6 +42,7 @@ import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.TestUtils; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.eclipse.aether.RepositorySystem; import org.junit.After; @@ -65,14 +67,14 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.stringContainsInOrder; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.MockitoAnnotations.openMocks; public class DisplayParentUpdatesMojoTest { private DisplayParentUpdatesMojo mojo; - private static ArtifactHandlerManager artifactHandlerManager; - private static RepositorySystem repositorySystem; private static ArtifactFactory artifactFactory; @@ -89,7 +91,7 @@ public class DisplayParentUpdatesMojoTest { @BeforeClass public static void setUpStatic() throws MojoExecutionException { - artifactHandlerManager = mockArtifactHandlerManager(); + ArtifactHandlerManager artifactHandlerManager = mockArtifactHandlerManager(); artifactFactory = new ArtifactFactory(artifactHandlerManager); repositorySystem = mockAetherRepositorySystem(new HashMap() { { @@ -106,14 +108,16 @@ public static void setUpStatic() throws MojoExecutionException { public void setUp() throws IllegalAccessException, IOException, MojoExecutionException { tempDir = TestUtils.createTempDir("display-property-updates"); tempFile = Files.createTempFile(tempDir, "output", ""); - mojo = new DisplayParentUpdatesMojo(artifactFactory, repositorySystem, null, null) { - { - setProject(createProject()); - reactorProjects = Collections.emptyList(); - session = mockMavenSession(); - mojoExecution = mock(MojoExecution.class); - } - }; + mojo = + new DisplayParentUpdatesMojo( + artifactFactory, repositorySystem, null, TestVersionChangeRecorder.asTestMap()) { + { + setProject(createProject()); + reactorProjects = Collections.emptyList(); + session = mockMavenSession(); + mojoExecution = mock(MojoExecution.class); + } + }; mojo.outputFile = tempFile.toFile(); mojo.setPluginContext(new HashMap<>()); openMocks(this); @@ -125,6 +129,10 @@ public void tearDown() throws Exception { } private MavenProject createProject() { + File baseDir = mock(File.class); + Path basePath = mock(Path.class); + doReturn(basePath).when(baseDir).toPath(); + doReturn(basePath).when(basePath).resolve(anyString()); return new MavenProject() { { setModel(new Model() { @@ -142,6 +150,12 @@ private MavenProject createProject() { setVersion("1.0.1-SNAPSHOT"); } }); + getBuild().setDirectory("target"); + } + + @Override + public File getBasedir() { + return baseDir; } }; } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/ForceReleasesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/ForceReleasesMojoTest.java index 3e3cf5f626..5e5e91cfc8 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/ForceReleasesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/ForceReleasesMojoTest.java @@ -14,10 +14,11 @@ import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; -import org.codehaus.mojo.versions.utils.TestChangeRecorder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.junit.Before; import org.junit.Test; @@ -59,7 +60,8 @@ * Unit tests for {@link ForceReleasesMojo} */ public class ForceReleasesMojoTest extends AbstractMojoTestCase { - private TestChangeRecorder changeRecorder; + private TestVersionChangeRecorder changeRecorder; + private ForceReleasesMojo mojo; @Mock @@ -80,8 +82,9 @@ public void setUp() throws Exception { artifactFactory = new ArtifactFactory(artifactHandlerManager); MavenSession session = mockMavenSession(); - changeRecorder = new TestChangeRecorder(); - mojo = new ForceReleasesMojo(artifactFactory, mockAetherRepositorySystem(), null, changeRecorder.asTestMap()); + mojo = new ForceReleasesMojo( + artifactFactory, mockAetherRepositorySystem(), null, TestVersionChangeRecorder.asTestMap()); + changeRecorder = (TestVersionChangeRecorder) mojo.getChangeRecorder(); setVariableValueToObject(mojo, "reactorProjects", emptyList()); mojo.project = new MavenProject() { { @@ -125,9 +128,12 @@ public void testProcessParent() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.0-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test @@ -152,9 +158,12 @@ public void testReplaceSnapshotWithRelease() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.0-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test @@ -179,9 +188,12 @@ public void testUpgrade() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.1.0-SNAPSHOT", "2.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.1.0-SNAPSHOT") + .withNewVersion("2.0.0"))); } @Test @@ -206,9 +218,12 @@ public void testDowngrade() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "2.1.0-SNAPSHOT", "2.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("2.1.0-SNAPSHOT") + .withNewVersion("2.0.0"))); } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/LockSnapshotsMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/LockSnapshotsMojoTest.java index 1a3fc01804..88c11e2182 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/LockSnapshotsMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/LockSnapshotsMojoTest.java @@ -33,6 +33,7 @@ import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.resolution.VersionRequest; @@ -80,7 +81,7 @@ public void setUp() throws MojoExecutionException { } private LockSnapshotsMojo createMojo(RepositorySystem repositorySystem) throws MojoExecutionException { - return new LockSnapshotsMojo(artifactFactory, repositorySystem, null, null) { + return new LockSnapshotsMojo(artifactFactory, repositorySystem, null, TestVersionChangeRecorder.asTestMap()) { { reactorProjects = emptyList(); project = new MavenProject(new Model() { diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SeparatePatternsForIncludesAnExcludesTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SeparatePatternsForIncludesAnExcludesTest.java index 9b1b7dd8f0..cd42b25d65 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SeparatePatternsForIncludesAnExcludesTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SeparatePatternsForIncludesAnExcludesTest.java @@ -7,6 +7,7 @@ import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.ArtifactFactory; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.junit.Before; import org.junit.Test; @@ -37,30 +38,32 @@ public void setUp() throws Exception { artifactFactory = new ArtifactFactory(artifactHandlerManager); pomHelper = new PomHelper(artifactFactory, expressionEvaluator); - mojo = new AbstractVersionsDependencyUpdaterMojo(artifactFactory, null, null, null) { - @Override - protected boolean getProcessDependencies() { - return true; - } - - @Override - protected boolean getProcessDependencyManagement() { - return true; - } - - @Override - public boolean getProcessParent() { - return false; - } - - @Override - protected boolean getAllowSnapshots() { - return false; - } - - @Override - protected void update(MutableXMLStreamReader pom) {} - }; + mojo = + new AbstractVersionsDependencyUpdaterMojo( + artifactFactory, null, null, TestVersionChangeRecorder.asTestMap()) { + @Override + protected boolean getProcessDependencies() { + return true; + } + + @Override + protected boolean getProcessDependencyManagement() { + return true; + } + + @Override + public boolean getProcessParent() { + return false; + } + + @Override + protected boolean getAllowSnapshots() { + return false; + } + + @Override + protected void update(MutableXMLStreamReader pom) {} + }; } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SetMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SetMojoTest.java index b9dee1b6de..03a2b43747 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SetMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/SetMojoTest.java @@ -24,6 +24,7 @@ import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.TestLog; import org.codehaus.mojo.versions.utils.TestUtils; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -73,7 +74,7 @@ public void tearDown() throws IOException { @Test public void testGetIncrementedVersion() throws MojoExecutionException { - new SetMojo(artifactFactory, null, null, null, null, null) { + new SetMojo(artifactFactory, null, null, null, TestVersionChangeRecorder.asTestMap(), null) { { assertThat(getIncrementedVersion("1", null), is("2-SNAPSHOT")); assertThat(getIncrementedVersion("1.0", null), is("1.1-SNAPSHOT")); @@ -89,7 +90,7 @@ public void testGetIncrementedVersion() throws MojoExecutionException { @Test public void testNextSnapshotIndexLowerBound() throws MojoExecutionException { - new SetMojo(artifactFactory, null, null, null, null, null) { + new SetMojo(artifactFactory, null, null, null, TestVersionChangeRecorder.asTestMap(), null) { { try { getIncrementedVersion("1.0.0", 0); @@ -103,7 +104,7 @@ public void testNextSnapshotIndexLowerBound() throws MojoExecutionException { @Test public void testNextSnapshotIndexUpperBound() throws MojoExecutionException { - new SetMojo(artifactFactory, null, null, null, null, null) { + new SetMojo(artifactFactory, null, null, null, TestVersionChangeRecorder.asTestMap(), null) { { try { getIncrementedVersion("1.0.0", 4); @@ -121,7 +122,7 @@ public void testNextSnapshotIndexUpperBound() throws MojoExecutionException { @Test public void testNextSnapshotIndexWithoutNextSnapshot() throws MojoFailureException { try { - new SetMojo(artifactFactory, null, null, null, null, null) { + new SetMojo(artifactFactory, null, null, null, TestVersionChangeRecorder.asTestMap(), null) { { project = new MavenProject(); project.setParent(new MavenProject()); @@ -277,7 +278,7 @@ public void testIssue1137() throws Exception { @Test public void testNextSnapshotIndexToIncrement() throws MojoExecutionException { - new SetMojo(artifactFactory, null, null, null, null, null) { + new SetMojo(artifactFactory, null, null, null, TestVersionChangeRecorder.asTestMap(), null) { { nextSnapshot = true; assertThat(getIncrementedVersion("1.1.1-SNAPSHOT", 1), is("2.0.0-SNAPSHOT")); diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java index 55f2d5ba6c..a932283e85 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java @@ -31,8 +31,10 @@ import org.apache.maven.plugin.testing.stubs.DefaultArtifactHandlerStub; import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.eclipse.aether.RepositorySystem; import org.junit.BeforeClass; import org.junit.Test; @@ -71,7 +73,7 @@ public static void setUpStatic() { @Override protected UseLatestVersionsMojoBase createMojo() throws IllegalAccessException, MojoExecutionException { - return new UpdateParentMojo(artifactFactory, repositorySystem, null, changeRecorder.asTestMap()) { + return new UpdateParentMojo(artifactFactory, repositorySystem, null, TestVersionChangeRecorder.asTestMap()) { { setProject(createProject()); reactorProjects = Collections.emptyList(); @@ -224,8 +226,12 @@ public void testParentDowngradeAllowed() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "parent-artifact", "1.0.1-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("parent-artifact") + .withOldVersion("1.0.1-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test @@ -252,8 +258,12 @@ public void testParentDowngradeAllowedWithRange() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "parent-artifact", "[1.0.1-SNAPSHOT,)", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("parent-artifact") + .withOldVersion("[1.0.1-SNAPSHOT,)") + .withNewVersion("1.0.0"))); } @Test @@ -281,8 +291,12 @@ public void testAllowSnapshots() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "issue-670-artifact", "0.0.1-1", "0.0.1-1-impl-SNAPSHOT"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("issue-670-artifact") + .withOldVersion("0.0.1-1") + .withNewVersion("0.0.1-1-impl-SNAPSHOT"))); } @Test @@ -302,8 +316,12 @@ public void testAllowSnapshotsWithParentVersion() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "issue-670-artifact", "0.0.1-1", "0.0.1-1-impl-SNAPSHOT"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("issue-670-artifact") + .withOldVersion("0.0.1-1") + .withNewVersion("0.0.1-1-impl-SNAPSHOT"))); } @Test @@ -343,7 +361,12 @@ private void testSkipResolution(String version) tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "parent-artifact", "1.0.0", version))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("parent-artifact") + .withOldVersion("1.0.0") + .withNewVersion(version))); } @Test @@ -362,8 +385,12 @@ public void testShouldUpgradeToSnapshot() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "parent-artifact", "0.9.0", "1.0.1-SNAPSHOT"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("parent-artifact") + .withOldVersion("0.9.0") + .withNewVersion("1.0.1-SNAPSHOT"))); } @Test @@ -384,7 +411,12 @@ public void testAllowMinorUpdates() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "parent-artifact", "0.8.0", "0.9.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("parent-artifact") + .withOldVersion("0.8.0") + .withNewVersion("0.9.0"))); } @Test @@ -404,7 +436,12 @@ public void testAllowIncrementalUpdates() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "test-incremental", "1.1.0", "1.1.1"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("test-incremental") + .withOldVersion("1.1.0") + .withNewVersion("1.1.1"))); } @Test @@ -423,7 +460,12 @@ public void testParentVersionRange() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "dummy-parent2", "1.0", "2.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("dummy-parent2") + .withOldVersion("1.0") + .withNewVersion("2.0"))); } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTest.java index 70d5265d08..2dc400c448 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTest.java @@ -19,9 +19,10 @@ import java.nio.file.Paths; import java.util.HashMap; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; -import org.codehaus.mojo.versions.utils.TestChangeRecorder; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.TestUtils; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.junit.Test; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; @@ -44,7 +45,12 @@ public void testAllowMajorUpdates() throws Exception { setUpMojo("update-properties").execute(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "default-artifact", "1.0.0", "2.0.0-M1"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROPERTY_UPDATE) + .withGroupId("default-group") + .withArtifactId("default-artifact") + .withOldVersion("1.0.0") + .withNewVersion("2.0.0-M1"))); } @Test @@ -58,8 +64,12 @@ public void testAllowMinorUpdates() throws Exception { mojo.execute(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "default-artifact", "1.0.0", "1.1.0-alpha"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROPERTY_UPDATE) + .withGroupId("default-group") + .withArtifactId("default-artifact") + .withOldVersion("1.0.0") + .withNewVersion("1.1.0-alpha"))); } @Test @@ -74,15 +84,20 @@ public void testAllowIncrementalUpdates() throws Exception { mojo.execute(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "default-artifact", "1.0.0", "1.0.1-rc1"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROPERTY_UPDATE) + .withGroupId("default-group") + .withArtifactId("default-artifact") + .withOldVersion("1.0.0") + .withNewVersion("1.0.1-rc1"))); } @Test public void testChangesNotRegisteredIfNoUpdatesInPom() throws Exception { TestUtils.copyDir(Paths.get("src/test/resources/org/codehaus/mojo/update-properties/issue-837"), pomDir); UpdatePropertiesMojo mojo = setUpMojo("update-properties"); - TestChangeRecorder changeRecorder = new TestChangeRecorder(); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + TestVersionChangeRecorder changeRecorder = new TestVersionChangeRecorder(); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); setVariableValueToObject(mojo, "changeRecorderFormat", "none"); // pomHelperClass.when( () -> PomHelper.setPropertyVersion( any(), anyString(), anyString(), // anyString() ) ) diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTestBase.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTestBase.java index 3af96ae0b4..ca93e8f850 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTestBase.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertiesMojoTestBase.java @@ -30,7 +30,7 @@ import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.apache.maven.plugin.testing.MojoRule; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.utils.TestChangeRecorder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.eclipse.aether.RepositorySystem; import org.junit.After; import org.junit.Before; @@ -52,7 +52,7 @@ public abstract class UpdatePropertiesMojoTestBase extends AbstractMojoTestCase protected Path pomDir; protected RepositorySystem repositorySystem; - protected TestChangeRecorder changeRecorder; + protected TestVersionChangeRecorder changeRecorder; @Before public void setUp() throws Exception { @@ -80,8 +80,8 @@ protected T setUpMojo(String goal) throws Exception { setVariableValueToObject(mojo, "repositorySystem", repositorySystem); setVariableValueToObject(mojo, "generateBackupPoms", false); setVariableValueToObject(mojo, "changeRecorderFormat", "none"); - changeRecorder = new TestChangeRecorder(); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + changeRecorder = new TestVersionChangeRecorder(); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); return (T) mojo; } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertyMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertyMojoTest.java index 815b07412b..3605964fff 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertyMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UpdatePropertyMojoTest.java @@ -18,7 +18,8 @@ import java.nio.file.Files; import java.nio.file.Paths; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.hamcrest.Matchers; import org.junit.Test; @@ -40,8 +41,12 @@ public void testAllowMajorUpdates() throws Exception { mojo.execute(); assertThat( changeRecorder.getChanges(), - Matchers.hasItem( - new DefaultDependencyVersionChange("default-group", "default-artifact", "1.0.0", "2.0.0-M1"))); + Matchers.hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROPERTY_UPDATE) + .withGroupId("default-group") + .withArtifactId("default-artifact") + .withOldVersion("1.0.0") + .withNewVersion("2.0.0-M1"))); } @Test @@ -56,8 +61,12 @@ public void testAllowMinorUpdates() throws Exception { mojo.execute(); assertThat( changeRecorder.getChanges(), - Matchers.hasItem(new DefaultDependencyVersionChange( - "default-group", "default-artifact", "1.0.0", "1.1.0-alpha"))); + Matchers.hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROPERTY_UPDATE) + .withGroupId("default-group") + .withArtifactId("default-artifact") + .withOldVersion("1.0.0") + .withNewVersion("1.1.0-alpha"))); } @Test @@ -73,8 +82,12 @@ public void testAllowIncrementalUpdates() throws Exception { mojo.execute(); assertThat( changeRecorder.getChanges(), - Matchers.hasItem( - new DefaultDependencyVersionChange("default-group", "default-artifact", "1.0.0", "1.0.1-rc1"))); + Matchers.hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PROPERTY_UPDATE) + .withGroupId("default-group") + .withArtifactId("default-artifact") + .withOldVersion("1.0.0") + .withNewVersion("1.0.1-rc1"))); } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseDepVersionMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseDepVersionMojoTest.java index 0c6d57f502..eb5076d125 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseDepVersionMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseDepVersionMojoTest.java @@ -29,10 +29,11 @@ import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.apache.maven.plugin.testing.MojoRule; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; -import org.codehaus.mojo.versions.change.DefaultPropertyVersionChange; -import org.codehaus.mojo.versions.utils.TestChangeRecorder; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; import org.codehaus.mojo.versions.utils.TestUtils; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -62,7 +63,7 @@ public class UseDepVersionMojoTest extends AbstractMojoTestCase { private Path tempDir; - private TestChangeRecorder changeRecorder = new TestChangeRecorder(); + private TestVersionChangeRecorder changeRecorder = new TestVersionChangeRecorder(); @Before public void setUp() throws Exception { @@ -131,12 +132,12 @@ public boolean isDebugEnabled() { }; TestUtils.copyDir( Paths.get("src/test/resources/org/codehaus/mojo/use-dep-version/properties/simple-profiles"), tempDir); - TestChangeRecorder changeRecorder = new TestChangeRecorder(); + TestVersionChangeRecorder changeRecorder = new TestVersionChangeRecorder(); UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); setVariableValueToObject(mojo, "log", logger); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.execute(); @@ -145,7 +146,10 @@ public boolean isDebugEnabled() { assertThat(pom, containsString("2.0.0")); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultPropertyVersionChange("revision", "1.0.0-SNAPSHOT", "2.0.0"))); + hasItem(new PropertyVersionChange() + .withProperty("revision") + .withOldValue("1.0.0-SNAPSHOT") + .withNewValue("2.0.0"))); } /** @@ -159,16 +163,15 @@ public void testPropertiesConflict() throws Exception { Log logger = mock(Log.class); StringBuilder warnLog = new StringBuilder(); doAnswer(i -> warnLog.append(i.getArgument(0).toString())).when(logger).warn(anyString()); - TestChangeRecorder changeRecorder = new TestChangeRecorder(); + TestVersionChangeRecorder changeRecorder = new TestVersionChangeRecorder(); TestUtils.copyDir( Paths.get("src/test/resources/org/codehaus/mojo/use-dep-version/properties/conflict"), tempDir); UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); setVariableValueToObject(mojo, "log", logger); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); mojo.execute(); @@ -194,7 +197,7 @@ public void testPropertiesConflictRedefinition() throws Exception { UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.execute(); @@ -205,7 +208,11 @@ public void testPropertiesConflictRedefinition() throws Exception { assertThat(child, containsString("2.0.0")); assertThat(parent, containsString("1.0.0-SNAPSHOT")); assertThat( - changeRecorder.getChanges(), hasItem(new DefaultPropertyVersionChange("revision", "1.0.1", "2.0.0"))); + changeRecorder.getChanges(), + hasItem(new PropertyVersionChange() + .withProperty("revision") + .withOldValue("1.0.1") + .withNewValue("2.0.0"))); } /** @@ -224,7 +231,7 @@ public void testPropertiesConflictCancellation() throws Exception { UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.execute(); @@ -236,7 +243,10 @@ public void testPropertiesConflictCancellation() throws Exception { assertThat(child, containsString("1.0.1")); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultPropertyVersionChange("revision", "1.0.0-SNAPSHOT", "2.0.0"))); + hasItem(new PropertyVersionChange() + .withProperty("revision") + .withOldValue("1.0.0-SNAPSHOT") + .withNewValue("2.0.0"))); } /** @@ -253,7 +263,7 @@ public void testPropertiesConflictCancellationProfiles() throws Exception { UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.execute(); @@ -265,7 +275,10 @@ public void testPropertiesConflictCancellationProfiles() throws Exception { assertThat(child, containsString("1.0.1")); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultPropertyVersionChange("revision", "1.0.0-SNAPSHOT", "2.0.0"))); + hasItem(new PropertyVersionChange() + .withProperty("revision") + .withOldValue("1.0.0-SNAPSHOT") + .withNewValue("2.0.0"))); } /** @@ -288,7 +301,7 @@ public boolean isDebugEnabled() { setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); setVariableValueToObject(mojo, "log", logger); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.execute(); @@ -297,7 +310,11 @@ public boolean isDebugEnabled() { assertThat(child, containsString("${revision}")); assertThat(parent, containsString("2.0.0")); assertThat( - changeRecorder.getChanges(), hasItem(new DefaultPropertyVersionChange("revision", "1.0.0", "2.0.0"))); + changeRecorder.getChanges(), + hasItem(new PropertyVersionChange() + .withProperty("revision") + .withOldValue("1.0.0") + .withNewValue("2.0.0"))); } /** @@ -314,7 +331,7 @@ public void testPropertiesChildParentRedefinition() throws Exception { UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.execute(); @@ -324,7 +341,11 @@ public void testPropertiesChildParentRedefinition() throws Exception { assertThat(parent, containsString("1.0.0-SNAPSHOT")); assertThat(child, containsString("2.0.0")); assertThat( - changeRecorder.getChanges(), hasItem(new DefaultPropertyVersionChange("revision", "1.0.1", "2.0.0"))); + changeRecorder.getChanges(), + hasItem(new PropertyVersionChange() + .withProperty("revision") + .withOldValue("1.0.1") + .withNewValue("2.0.0"))); } /** @@ -340,7 +361,7 @@ public void testPropertyFromParent() throws Exception { doAnswer(i -> log.append("[WARN] ").append(i.getArgument(0).toString())) .when(logger) .warn(anyString()); - TestChangeRecorder changeRecorder = new TestChangeRecorder(); + TestVersionChangeRecorder changeRecorder = new TestVersionChangeRecorder(); TestUtils.copyDir( Paths.get("src/test/resources/org/codehaus/mojo/use-dep-version/properties/child-parent"), tempDir); @@ -348,9 +369,8 @@ public void testPropertyFromParent() throws Exception { mojoRule.lookupConfiguredMojo(tempDir.resolve("child").toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); setVariableValueToObject(mojo, "log", logger); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); mojo.execute(); @@ -369,7 +389,7 @@ public void testVersionlessDependency() throws Exception { UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); setVariableValueToObject(mojo, "log", logger); mojo.depVersion = "2.0.0"; mojo.forceVersion = true; @@ -392,7 +412,7 @@ public void testDependencyManagemenent() throws Exception { UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.depVersion = "2.0.0"; mojo.forceVersion = true; setVariableValueToObject(mojo, "processDependencies", false); @@ -403,7 +423,12 @@ public void testDependencyManagemenent() throws Exception { assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "artifactA", "1.0.0", "2.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0") + .withNewVersion("2.0.0"))); } @Test @@ -417,7 +442,7 @@ public void testVersionDefinedInDependencyManagemenent() throws Exception { UseDepVersionMojo mojo = fixAllProjects(mojoRule.lookupConfiguredMojo(tempDir.toFile(), "use-dep-version")); setVariableValueToObject(mojo, "reactorProjects", Collections.singletonList(mojo.getProject())); setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); setVariableValueToObject(mojo, "log", logger); mojo.depVersion = "2.0.0"; mojo.forceVersion = true; @@ -433,7 +458,12 @@ public void testVersionDefinedInDependencyManagemenent() throws Exception { "[WARN] Not updating default-group:artifactA in dependencies: version defined in dependencyManagement")); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "artifactA", "1.0.0", "2.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0") + .withNewVersion("2.0.0"))); } @Test @@ -473,7 +503,7 @@ public boolean isDebugEnabled() { mojo.forceVersion = true; setVariableValueToObject(mojo, "repositorySystem", mockAetherRepositorySystem()); setVariableValueToObject(mojo, "log", logger); - setVariableValueToObject(mojo, "changeRecorders", changeRecorder.asTestMap()); + setVariableValueToObject(mojo, "changeRecorder", changeRecorder); mojo.execute(); diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestReleasesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestReleasesMojoTest.java index dfc2340e6e..863dee0ce4 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestReleasesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestReleasesMojoTest.java @@ -25,7 +25,8 @@ import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.DependencyBuilder; import org.hamcrest.Matchers; import org.junit.Test; @@ -110,9 +111,12 @@ public void testAllowDowngrade() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.1-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.1-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java index fc7b67d9b1..3a9798ad63 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java @@ -27,7 +27,8 @@ import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.DependencyBuilder; import org.junit.Test; @@ -98,8 +99,12 @@ public void testDependenciesDowngradeIncremental() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "dependency-artifact", "1.1.1-SNAPSHOT", "1.1.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.1-SNAPSHOT") + .withNewVersion("1.1.0"))); } @Test @@ -127,9 +132,12 @@ public void testDependenciesDowngradeMinor() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "dependency-artifact", - "1.1.0-SNAPSHOT", "1.1.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.0-SNAPSHOT") + .withNewVersion("1.1.0"))); } @Test @@ -146,9 +154,12 @@ public void testDependenciesDowngradeMajor() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "dependency-artifact", - "1.1.1-SNAPSHOT", "1.1.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.1-SNAPSHOT") + .withNewVersion("1.1.0"))); } @Test @@ -165,8 +176,12 @@ public void testDependencyManagementDowngrade() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "dependency-artifact", "1.1.1-SNAPSHOT", "1.1.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_MANAGEMENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.1-SNAPSHOT") + .withNewVersion("1.1.0"))); } @Test @@ -194,8 +209,12 @@ public void testParentDowngrade() tryUpdate(); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "dependency-artifact", "1.1.1-SNAPSHOT", "1.1.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.1-SNAPSHOT") + .withNewVersion("1.1.0"))); } @Test @@ -234,8 +253,12 @@ public void testPoisonDependencyVersion() // being present in the dependency list assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "dependency-artifact", "1.1.1-SNAPSHOT", "1.1.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.1-SNAPSHOT") + .withNewVersion("1.1.0"))); } @Test @@ -261,7 +284,12 @@ public void testDontUpgradeToPreReleaseByDefault() // With allowPreReleases=false (default), beta is excluded and 1.1.0 is selected assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "pre-release-artifact", "1.0.0", "1.1.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("pre-release-artifact") + .withOldVersion("1.0.0") + .withNewVersion("1.1.0"))); } @Test @@ -287,7 +315,11 @@ public void testUpgradeToPreReleaseWhenAllowed() // Beta version 1.2.0-beta1 is highest and will be selected assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "pre-release-artifact", "1.0.0", "1.2.0-beta1"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("pre-release-artifact") + .withOldVersion("1.0.0") + .withNewVersion("1.2.0-beta1"))); } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java index 86cdd1cfa2..1d03c96683 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java @@ -16,10 +16,11 @@ import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; -import org.codehaus.mojo.versions.utils.TestChangeRecorder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.eclipse.aether.RepositorySystem; import org.hamcrest.core.Is; @@ -48,7 +49,7 @@ public abstract class UseLatestVersionsMojoTestBase { protected UseLatestVersionsMojoBase mojo; - protected TestChangeRecorder changeRecorder; + protected TestVersionChangeRecorder changeRecorder; @Mock protected Log log; @@ -65,11 +66,11 @@ public abstract class UseLatestVersionsMojoTestBase { @Before public void setUp() throws Exception { openMocks(this); - changeRecorder = new TestChangeRecorder(); ArtifactHandlerManager artifactHandlerManager = mockArtifactHandlerManager(); artifactFactory = new ArtifactFactory(artifactHandlerManager); pomHelper = new PomHelper(artifactFactory, expressionEvaluator); mojo = createMojo(); + changeRecorder = (TestVersionChangeRecorder) mojo.getChangeRecorder(); mojo.mojoExecution = Mockito.mock(MojoExecution.class); } @@ -153,8 +154,12 @@ protected void testIncludeFilter(String expectedNewVersion) assertThat(changeRecorder.getChanges(), hasSize(1)); assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "other-artifact", "1.0", expectedNewVersion))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("other-artifact") + .withOldVersion("1.0") + .withNewVersion(expectedNewVersion))); } @Test @@ -193,8 +198,12 @@ protected void testExcludeFilter(String expectedNewVersion) assertThat(changeRecorder.getChanges(), hasSize(1)); assertThat( changeRecorder.getChanges(), - not(hasItem(new DefaultDependencyVersionChange( - "default-group", "other-artifact", "1.0", expectedNewVersion)))); + not(hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("other-artifact") + .withOldVersion("1.0") + .withNewVersion(expectedNewVersion)))); } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsRaceConditionTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsRaceConditionTest.java index cec04f1732..93d73ab9fe 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsRaceConditionTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsRaceConditionTest.java @@ -14,11 +14,12 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.PomHelper; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; import org.codehaus.mojo.versions.utils.MockUtils; -import org.codehaus.mojo.versions.utils.TestChangeRecorder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.junit.Before; import org.junit.Test; @@ -43,7 +44,7 @@ public class UseLatestVersionsRaceConditionTest { protected UseLatestVersionsMojoBase mojo; - protected TestChangeRecorder changeRecorder; + protected TestVersionChangeRecorder changeRecorder; @Mock protected Log log; @@ -58,7 +59,7 @@ public class UseLatestVersionsRaceConditionTest { @Before public void setUp() throws Exception { openMocks(this); - changeRecorder = new TestChangeRecorder(); + changeRecorder = new TestVersionChangeRecorder(); ArtifactHandlerManager artifactHandlerManager = mockArtifactHandlerManager(); artifactFactory = new ArtifactFactory(artifactHandlerManager); pomHelper = new PomHelper(artifactFactory, expressionEvaluator); @@ -103,8 +104,9 @@ protected UseLatestVersionsMojoBase createMojo() throws IllegalAccessException, artifactFactory, MockUtils.mockAetherRepositorySystem(), Collections.singletonMap("proto", testWagon), - changeRecorder.asTestMap()) { + TestVersionChangeRecorder.asTestMap()) { { + changeRecorder = (TestVersionChangeRecorder) getChangeRecorder(); reactorProjects = emptyList(); MavenProject project = new MavenProject() { { @@ -168,11 +170,17 @@ public void testConcurrency() throws Exception { assertThat( changeRecorder.getChanges(), allOf( - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.0", "2.0.0")), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactB", - "1.0.0", "1.1.0")))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0") + .withNewVersion("2.0.0")), + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactB") + .withOldVersion("1.0.0") + .withNewVersion("1.1.0")))); } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextReleasesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextReleasesMojoTest.java index 9685bac48b..4152c89fd4 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextReleasesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextReleasesMojoTest.java @@ -27,7 +27,8 @@ import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.DependencyBuilder; import org.hamcrest.Matchers; import org.junit.Test; @@ -128,7 +129,12 @@ public void testFindANewerRelease() throws IllegalAccessException { } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange("default-group", "dependency-artifact", "1.1.0", "1.1.1"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.0") + .withNewVersion("1.1.1"))); } @Test @@ -160,9 +166,12 @@ public void testAllowDowngrade() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.1-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.1-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextVersionsMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextVersionsMojoTest.java index 24ab055997..56c3fffe09 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextVersionsMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseNextVersionsMojoTest.java @@ -27,7 +27,8 @@ import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.utils.DependencyBuilder; import org.hamcrest.Matchers; import org.junit.Test; @@ -129,8 +130,12 @@ public void testFindANewerVersion() throws IllegalAccessException { } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "dependency-artifact", "1.1.0-SNAPSHOT", "1.1.1"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("dependency-artifact") + .withOldVersion("1.1.0-SNAPSHOT") + .withNewVersion("1.1.1"))); } @Test @@ -162,9 +167,12 @@ public void testAllowDowngrade() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.1-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.1-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseReleasesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseReleasesMojoTest.java index 00beb1b784..01a8328f59 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseReleasesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseReleasesMojoTest.java @@ -15,11 +15,12 @@ import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.api.PomHelper; import org.codehaus.mojo.versions.api.VersionRetrievalException; -import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +import org.codehaus.mojo.versions.model.DependencyChangeKind; +import org.codehaus.mojo.versions.model.DependencyVersionChange; import org.codehaus.mojo.versions.rule.RuleService; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; -import org.codehaus.mojo.versions.utils.TestChangeRecorder; +import org.codehaus.mojo.versions.utils.TestVersionChangeRecorder; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.junit.Before; import org.junit.Test; @@ -62,7 +63,8 @@ * Unit tests for {@link UseReleasesMojo} */ public class UseReleasesMojoTest extends AbstractMojoTestCase { - private TestChangeRecorder changeRecorder; + private TestVersionChangeRecorder changeRecorder; + private UseReleasesMojo mojo; @Mock @@ -84,8 +86,9 @@ public void setUp() throws Exception { ArtifactHandlerManager artifactHandlerManager = mockArtifactHandlerManager(); artifactFactory = new ArtifactFactory(artifactHandlerManager); MavenSession mavenSession = mockMavenSession(); - changeRecorder = new TestChangeRecorder(); - mojo = new UseReleasesMojo(artifactFactory, mockAetherRepositorySystem(), null, changeRecorder.asTestMap()); + mojo = new UseReleasesMojo( + artifactFactory, mockAetherRepositorySystem(), null, TestVersionChangeRecorder.asTestMap()); + changeRecorder = (TestVersionChangeRecorder) mojo.getChangeRecorder(); setVariableValueToObject(mojo, "reactorProjects", emptyList()); mojo.mojoExecution = mock(MojoExecution.class); mojo.project = new MavenProject() { @@ -129,9 +132,12 @@ public void testProcessParent() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.0-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test @@ -172,9 +178,12 @@ public void testProcessTimestampedParent() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.0-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.PARENT_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test @@ -199,9 +208,12 @@ public void testReplaceSnapshotWithRelease() } assertThat( changeRecorder.getChanges(), - hasItem(new DefaultDependencyVersionChange( - "default-group", "artifactA", - "1.0.0-SNAPSHOT", "1.0.0"))); + hasItem(new DependencyVersionChange() + .withKind(DependencyChangeKind.DEPENDENCY_UPDATE) + .withGroupId("default-group") + .withArtifactId("artifactA") + .withOldVersion("1.0.0-SNAPSHOT") + .withNewVersion("1.0.0"))); } @Test diff --git a/versions-model/pom.xml b/versions-model/pom.xml index b86aaba371..79dd7a9c67 100644 --- a/versions-model/pom.xml +++ b/versions-model/pom.xml @@ -12,6 +12,17 @@ Versions Model Modello models used in plugin + + + javax.xml.bind + jaxb-api + + + org.apache.commons + commons-lang3 + + + @@ -21,8 +32,54 @@ *.mdo + + ${project.build.directory}/site/xsd + ${project.basedir}/src/main/resources/xsd + + *.xsd + + + + org.codehaus.mojo + jaxb2-maven-plugin + ${jaxb2MavenPlugin.version} + + + org.jvnet.jaxb2_commons + jaxb2-fluent-api + ${jaxb2FluentApi.version} + + + org.jvnet.jaxb2_commons + jaxb2-basics-annotate + ${jaxb2BasicsAnnotate.version} + + + + + xjc + + xjc + + + + src/main/resources/xsd/updates-3.0.xsd + + + src/main/resources/xsd/bindings.xjb + + ${project.build.directory}/generated-sources/jaxb + org.codehaus.mojo.versions.model + true + + -Xfluent-api + + + + + org.codehaus.modello modello-maven-plugin diff --git a/versions-model/src/main/java/org/codehaus/mojo/versions/model/VersionChangeBase.java b/versions-model/src/main/java/org/codehaus/mojo/versions/model/VersionChangeBase.java new file mode 100644 index 0000000000..8f9f9b5d59 --- /dev/null +++ b/versions-model/src/main/java/org/codehaus/mojo/versions/model/VersionChangeBase.java @@ -0,0 +1,26 @@ +package org.codehaus.mojo.versions.model; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Base class for version changes to provide common implementations of Object methods. + */ +public abstract class VersionChangeBase { + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this, true); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj, true); + } +} diff --git a/versions-model/src/main/java/org/codehaus/mojo/versions/model/util/VersionChangeSelector.java b/versions-model/src/main/java/org/codehaus/mojo/versions/model/util/VersionChangeSelector.java new file mode 100644 index 0000000000..f05b88ce95 --- /dev/null +++ b/versions-model/src/main/java/org/codehaus/mojo/versions/model/util/VersionChangeSelector.java @@ -0,0 +1,48 @@ +package org.codehaus.mojo.versions.model.util; + +import org.codehaus.mojo.versions.model.DependencyVersionChange; +import org.codehaus.mojo.versions.model.PropertyVersionChange; +import org.codehaus.mojo.versions.model.VersionChange; + +/** + * Enum to select between different {@link VersionChange} types. + */ +public enum VersionChangeSelector { + /** + * Selects a {@link DependencyVersionChange}. + */ + DEPENDENCY, + /** + * Selects a {@link PropertyVersionChange}. + */ + PROPERTY; + + /** + * Selects the appropriate enum constant for the given {@link VersionChange} instance. + * @param versionChange the version change instance + * @param the type of the version change + * @return the corresponding enum constant + */ + public static VersionChangeSelector valueOf(T versionChange) { + if (versionChange instanceof DependencyVersionChange) { + return DEPENDENCY; + } + return PROPERTY; + } + + /** + * Creates a new {@link VersionChange} instance based on the enum constant. + * @param the type of the version change + * @return the corresponding version change instance + */ + @SuppressWarnings("unchecked") + public T toVersionChange() { + if (this == DEPENDENCY) return (T) new DependencyVersionChange(); + return (T) new PropertyVersionChange(); + } + + @Override + public String toString() { + return name().toLowerCase(); + } +} diff --git a/versions-model/src/main/java/org/codehaus/mojo/versions/model/xjb/ZonedDateTimeXmlAdapter.java b/versions-model/src/main/java/org/codehaus/mojo/versions/model/xjb/ZonedDateTimeXmlAdapter.java new file mode 100644 index 0000000000..d91da4e1c1 --- /dev/null +++ b/versions-model/src/main/java/org/codehaus/mojo/versions/model/xjb/ZonedDateTimeXmlAdapter.java @@ -0,0 +1,29 @@ +package org.codehaus.mojo.versions.model.xjb; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Adapter for JAXB to handle {@link ZonedDateTime} serialization and deserialization. + */ +public class ZonedDateTimeXmlAdapter { + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + /** + * Parses a string into a {@link ZonedDateTime}. + * @param v the string to parse + * @return the parsed ZonedDateTime + */ + public static ZonedDateTime parse(String v) { + return (v == null) ? null : ZonedDateTime.parse(v, FORMATTER); + } + + /** + * Formats a {@link ZonedDateTime} into a string. + * @param v the ZonedDateTime to format + * @return the formatted string + */ + public static String print(ZonedDateTime v) { + return (v == null) ? null : v.format(FORMATTER); + } +} diff --git a/versions-model/src/main/resources/xsd/bindings.xjb b/versions-model/src/main/resources/xsd/bindings.xjb new file mode 100644 index 0000000000..4b1d9f4407 --- /dev/null +++ b/versions-model/src/main/resources/xsd/bindings.xjb @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/versions-model/src/main/resources/xsd/updates-3.0.xsd b/versions-model/src/main/resources/xsd/updates-3.0.xsd new file mode 100644 index 0000000000..84f0e68b8d --- /dev/null +++ b/versions-model/src/main/resources/xsd/updates-3.0.xsd @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Represents a MavenProject (pom.xml) version update + + + + + Represents a regular dependency version update + + + + + Represents a dependencyManagement version update + + + + + Represents a version update of the parent MavenProject + + + + + Represents a plugin version update + + + + + Represents a pluginManagement version update + + + + + Represents a version update of a dependency associated with a property + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versions-model/src/site/markdown/xsd/index.md b/versions-model/src/site/markdown/xsd/index.md index 16c5d7b137..b641cfdf7f 100644 --- a/versions-model/src/site/markdown/xsd/index.md +++ b/versions-model/src/site/markdown/xsd/index.md @@ -11,3 +11,9 @@ Versions - XML schemas for ruleSet - [rule-2.1.0.xsd](rule-2.1.0.xsd) - [rule-2.0.0.xsd](rule-2.0.0.xsd) +Change recorder updates +======================= + +- [updates-3.0.xsd](updates-3.0.xsd) +- [updates-2.0.xsd](updates-2.0.xsd) (deprecated) + diff --git a/versions-model/src/site/resources/xsd/updates-2.0.xsd b/versions-model/src/site/resources/xsd/updates-2.0.xsd new file mode 100644 index 0000000000..6430ba2c78 --- /dev/null +++ b/versions-model/src/site/resources/xsd/updates-2.0.xsd @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Represents a MavenProject (pom.xml) version update + + + + + Represents a regular dependency version update + + + + + Represents a dependencyManagement version update + + + + + Represents a version update of the parent MavenProject + + + + + Represents a plugin version update + + + + + Represents a pluginManagement version update + + + + + Represents a version update of a dependency associated with a property + + + + + Represents an extension version update + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versions-test/pom.xml b/versions-test/pom.xml index d649d84291..4ee6b89ed5 100644 --- a/versions-test/pom.xml +++ b/versions-test/pom.xml @@ -36,6 +36,11 @@ versions-api ${project.version} + + org.codehaus.mojo.versions + versions-model + ${project.version} + org.apache.maven maven-artifact @@ -68,6 +73,10 @@ org.mockito mockito-core + + org.hamcrest + hamcrest + diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java index 3b82c2d135..2283355569 100644 --- a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java +++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java @@ -19,6 +19,8 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.apache.maven.plugin.logging.SystemStreamLog; + /** * A test utility provided a closeable temporary file, implementing {@link AutoCloseable}, which * deletes the temporary file on {@link #close()}, typically upon completion of a {@code try-finally} block. @@ -45,6 +47,10 @@ public CloseableTempFile(String prefix) throws IOException { @Override public void close() throws Exception { - Files.deleteIfExists(path); + try { + Files.deleteIfExists(path); + } catch (IOException e) { + new SystemStreamLog().error("Error deleting temporary directory " + path, e); + } } } diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java deleted file mode 100644 index 0fe36f09a9..0000000000 --- a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.codehaus.mojo.versions.utils; - -/* - * Copyright MojoHaus and Contributors - * Licensed 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 javax.inject.Named; - -import java.nio.file.Path; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.codehaus.mojo.versions.api.change.VersionChange; -import org.codehaus.mojo.versions.api.recording.ChangeRecorder; -import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; -import org.codehaus.mojo.versions.api.recording.PropertyChangeRecord; - -/** - * A simple {@link ChangeRecorder} implementation used in tests. - *

- * It records {@link VersionChange} instances reported via dependency or - * property change records into an in-memory list so tests can assert on them. - */ -@Named("test") -public class TestChangeRecorder implements ChangeRecorder { - /** - * Create a new test change recorder. - */ - public TestChangeRecorder() { - // explicit constructor to provide Javadoc for the no-arg constructor - } - - private final List changes = new LinkedList<>(); - - /** - * Record a dependency version change. - * - * @param changeRecord the dependency change record containing the version change - */ - @Override - public void recordChange(DependencyChangeRecord changeRecord) { - changes.add(changeRecord.getVersionChange()); - } - - /** - * Record a property version change. - * - * @param changeRecord the property change record containing the version change - */ - @Override - public void recordChange(PropertyChangeRecord changeRecord) { - changes.add(changeRecord.getVersionChange()); - } - - /** - * Write a report of recorded changes to the given output path. - *

- * This test implementation does nothing. - * - * @param outputPath the path where a report would be written - */ - @Override - public void writeReport(Path outputPath) {} - - /** - * Returns the list of recorded version changes in the order they were recorded. - * - * @return an unmodifiable view of the recorded version changes - */ - public List getChanges() { - return changes; - } - - /** - * Return a simple map suitable for injection in tests. The map contains a single - * entry with key {@code "none"} mapping to this recorder instance. - * - * @return a map with a single test change recorder entry - */ - public Map asTestMap() { - HashMap map = new HashMap<>(); - map.put("none", this); - return map; - } -} diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestVersionChangeRecorder.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestVersionChangeRecorder.java new file mode 100644 index 0000000000..dfa3fb6d59 --- /dev/null +++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestVersionChangeRecorder.java @@ -0,0 +1,84 @@ +package org.codehaus.mojo.versions.utils; + +/* + * Copyright MojoHaus and Contributors + * Licensed 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 javax.inject.Named; + +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorder; +import org.codehaus.mojo.versions.api.recording.VersionChangeRecorderFactory; +import org.codehaus.mojo.versions.model.VersionChange; +import org.codehaus.mojo.versions.model.VersionsExecution; + +/** + * A test implementation of VersionChangeRecorder that stores changes in memory for inspection. + * This implementation does not write any report to disk. + */ +@Named("test") +public class TestVersionChangeRecorder implements VersionChangeRecorderFactory, VersionChangeRecorder { + private final VersionsExecution versionsExecution = + new VersionsExecution().withDate(ZonedDateTime.now()).withGoal("test-goal"); + + /** + * Creates a new instance of TestVersionChangeRecorder. + */ + public TestVersionChangeRecorder() {} + + @Override + public void recordChange(VersionChange versionChange) { + versionsExecution.getVersionChanges().add(versionChange); + } + + @Override + public void writeReport(Path outputPath) {} + + @Override + public String getDefaultFileName() { + return "versions-changes.xml"; + } + + /** + * Gets the list of recorded version changes. + * @return the list of version changes + */ + public List getChanges() { + return versionsExecution.getVersionChanges(); + } + + /** + * Provides a map with a single entry mapping "none" to a new instance of TestVersionChangeRecorder. + * This can be used in testing scenarios where a VersionChangeRecorderFactory map is required. + * + * @return a map with "none" mapped to a TestVersionChangeRecorder instance + */ + public static Map asTestMap() { + return Collections.singletonMap("none", new TestVersionChangeRecorder()); + } + + @Override + public VersionChangeRecorder create( + MavenSession mavenSession, MojoExecution mojoExecution, Log log, Map ignored) { + return this; + } +}