diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java index 85ce4a8ae..0ee3df21f 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java @@ -663,8 +663,10 @@ else if ( !excludePropertiesList.isEmpty() && excludePropertiesList.contains( pr + builder.getVersionRange() ); property.setVersion( builder.getVersionRange() ); } - versions.setCurrentVersion( request.getMavenProject().getProperties() - .getProperty( property.getName() ) ); + final String currentVersion = request.getMavenProject().getProperties() + .getProperty( property.getName() ); + versions.setCurrentVersion( currentVersion ); + property.setValue( currentVersion ); propertyVersions.put( property, versions ); } catch ( VersionRetrievalException e ) diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java index 09b5f5612..395121df9 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java @@ -46,6 +46,13 @@ public class Property */ private String version; + /** + * Used by {@link org.codehaus.mojo.versions.utils.PropertyComparator} when comparing two same named properties + * + * @since 2.14.0 + */ + private String value; + /** * Whether to automatically link dependencies to the property. * @@ -105,6 +112,7 @@ public Property( String name ) this.searchReactor = true; this.preferReactor = true; this.version = null; + this.value = null; } public String getName() @@ -176,4 +184,14 @@ public void setBanSnapshots( boolean banSnapshots ) { this.banSnapshots = banSnapshots; } + + public String getValue() + { + return value; + } + + public void setValue( String value ) + { + this.value = value; + } } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java index 845995015..88112eec7 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java @@ -20,7 +20,6 @@ */ import java.util.Comparator; - import org.apache.commons.lang3.StringUtils; import org.codehaus.mojo.versions.api.Property; @@ -42,14 +41,18 @@ public enum PropertyComparator implements Comparator * @see java.util.Comparator#compare(Object, Object) * @since 1.0-beta-1 */ + @SuppressWarnings( "checkstyle:InnerAssignment" ) public int compare( Property p1, Property p2 ) { + int r; return p1 == p2 ? 0 : p1 == null - ? 1 - : p2 == null - ? -1 - : StringUtils.compare( p1.getName(), p2.getName() ); + ? 1 + : p2 == null + ? -1 + : ( r = StringUtils.compare( p1.getName(), p2.getName() ) ) == 0 + ? StringUtils.compare( p1.getValue(), p2.getValue() ) + : r ; } } diff --git a/versions-maven-plugin/src/it-repo/dummy-aggregate-child-333.pom b/versions-maven-plugin/src/it-repo/dummy-aggregate-child-333.pom new file mode 100644 index 000000000..d2358bef9 --- /dev/null +++ b/versions-maven-plugin/src/it-repo/dummy-aggregate-child-333.pom @@ -0,0 +1,38 @@ + + 4.0.0 + + + localhost + dummy-aggregate-parent + 1.0.1-SNAPSHOT + + + localhost + dummy-aggregate-child + 1.0.1-SNAPSHOT + pom + + + 2.0.0.0 + + + + + + test.bigversion + dummy-lib + ${version.dummy-lib} + + + + + + + test.package + module + 0.0.2.19 + + + + diff --git a/versions-maven-plugin/src/it-repo/dummy-aggregate-parent-333.pom b/versions-maven-plugin/src/it-repo/dummy-aggregate-parent-333.pom new file mode 100644 index 000000000..43659cde3 --- /dev/null +++ b/versions-maven-plugin/src/it-repo/dummy-aggregate-parent-333.pom @@ -0,0 +1,33 @@ + + 4.0.0 + + localhost + dummy-aggregate-parent + 1.0.1-SNAPSHOT + pom + + + 3.0.0 + + + + + + + maven-clean-plugin + ${version.maven-clean-plugin} + + + maven-deploy-plugin + 3.0.0-M1 + + + + + + + true + + + diff --git a/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/child-one/pom.xml b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/child-one/pom.xml new file mode 100644 index 000000000..8df7644fb --- /dev/null +++ b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/child-one/pom.xml @@ -0,0 +1,25 @@ + + 4.0.0 + + + localhost + it-dependency-updates-aggregate-report-333 + 1.0 + + + localhost + it-dependency-updates-aggregate-report-333-child-one + 1.0 + jar + http://localhost/ + + + + test.bigversion + dummy-lib + 3.0.0.0-SNAPSHOT + + + + diff --git a/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/child-two/pom.xml b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/child-two/pom.xml new file mode 100644 index 000000000..e1f678e74 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/child-two/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + + localhost + it-dependency-updates-aggregate-report-333 + 1.0 + + + localhost + it-dependency-updates-aggregate-report-333-child-two + 1.0 + jar + http://localhost/ + + diff --git a/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/invoker.properties b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/invoker.properties new file mode 100644 index 000000000..c01f7db0e --- /dev/null +++ b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/invoker.properties @@ -0,0 +1 @@ +invoker.goals=site diff --git a/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/pom.xml b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/pom.xml new file mode 100644 index 000000000..fe946378f --- /dev/null +++ b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/pom.xml @@ -0,0 +1,68 @@ + + 4.0.0 + + + localhost + dummy-aggregate-child + 1.0.1-SNAPSHOT + + + localhost + it-dependency-updates-aggregate-report-333 + 1.0 + pom + http://localhost/ + + + + + + localhost + dummy-api + 1.1 + + + localhost + dummy-impl + 1.1 + + + + + + + + + maven-site-plugin + @sitePluginVersion@ + + + + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + false + + + + dependency-updates-aggregate-report + + + + + + + + + child-one + child-two + + + diff --git a/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/src/site/site.xml b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/src/site/site.xml new file mode 100644 index 000000000..e95514848 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/src/site/site.xml @@ -0,0 +1,7 @@ + + + org.apache.maven.skins + maven-default-skin + 1.0 + + diff --git a/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/verify.groovy b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/verify.groovy new file mode 100644 index 000000000..4fc618e33 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dependency-updates-aggregate-report-issue-333/verify.groovy @@ -0,0 +1,15 @@ +output = new File( basedir, 'target/site/dependency-updates-aggregate-report.html' ).text + .replaceAll( '<[^>]+>', ' ' ) + .replaceAll( '&[^;]+;', ' ' ) + .replaceAll( '\\s+', ' ' ) + +// Dependency management +assert !( output =~ 'This project does not declare any dependencies in a dependencyManagement section.' ) +assert ( output =~ 'localhost dummy-api 1.1 jar' ) +assert ( output =~ 'localhost dummy-impl 1.1 jar' ) +assert ( output =~ 'test.bigversion dummy-lib 2.0.0.0 jar' ) + +// Dependencies +assert !( output =~ 'This project does not declare any dependencies.' ) +assert ( output =~ 'test.bigversion dummy-lib 3.0.0.0-SNAPSHOT compile jar' ) +assert ( output =~ 'test.package module 0.0.2.19 compile jar' ) diff --git a/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/child-one/pom.xml b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/child-one/pom.xml new file mode 100644 index 000000000..88cacf2bc --- /dev/null +++ b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/child-one/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + localhost + it-plugin-updates-aggregate-report-333 + 1.0 + + + localhost + it-plugin-updates-aggregate-report-333-child-one + 1.0 + jar + dependency-updates-report + http://localhost/ + + + + + maven-clean-plugin + 3.2.0 + + + + + + diff --git a/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/child-two/pom.xml b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/child-two/pom.xml new file mode 100644 index 000000000..c88648b24 --- /dev/null +++ b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/child-two/pom.xml @@ -0,0 +1,25 @@ + + 4.0.0 + + + localhost + it-plugin-updates-aggregate-report-333 + 1.0 + + + localhost + it-plugin-updates-aggregate-report-333-child-two + 1.0 + jar + http://localhost/ + + + + + maven-deploy-plugin + + + + + diff --git a/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/invoker.properties b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/invoker.properties new file mode 100644 index 000000000..c01f7db0e --- /dev/null +++ b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/invoker.properties @@ -0,0 +1 @@ +invoker.goals=site diff --git a/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/pom.xml b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/pom.xml new file mode 100644 index 000000000..ee5e25f6d --- /dev/null +++ b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/pom.xml @@ -0,0 +1,56 @@ + + 4.0.0 + + + localhost + dummy-aggregate-child + 1.0.1-SNAPSHOT + + + localhost + it-plugin-updates-aggregate-report-333 + 1.0 + pom + http://localhost/ + + + + + + maven-site-plugin + @sitePluginVersion@ + + + + + + maven-clean-plugin + 3.1.0 + + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + false + + + + plugin-updates-aggregate-report + + + + + + + + + child-one + child-two + + diff --git a/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/src/site/site.xml b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/src/site/site.xml new file mode 100644 index 000000000..e95514848 --- /dev/null +++ b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/src/site/site.xml @@ -0,0 +1,7 @@ + + + org.apache.maven.skins + maven-default-skin + 1.0 + + diff --git a/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/verify.groovy b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/verify.groovy new file mode 100644 index 000000000..4c672cfe9 --- /dev/null +++ b/versions-maven-plugin/src/it/it-plugin-updates-aggregate-report-issue-333/verify.groovy @@ -0,0 +1,13 @@ +output = new File( basedir, 'target/site/plugin-updates-aggregate-report.html' ).text + .replaceAll( '<[^>]+>', ' ' ) + .replaceAll( '&[^;]+;', ' ' ) + .replaceAll( '\\s+', ' ' ) + +// Plugin management +assert !( output =~ 'This project does not declare any plugins in a build/pluginManagement section.' ) +assert ( output =~ 'org.apache.maven.plugins maven-clean-plugin 3.0.0' ) + +// Plugins +assert !( output =~ 'This project does not declare any plugins in a build/plugins section.' ) +assert ( output =~ 'org.apache.maven.plugins maven-clean-plugin 3.1.0' ) +assert ( output =~ 'org.apache.maven.plugins maven-clean-plugin 3.2.0' ) diff --git a/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/child-one/pom.xml b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/child-one/pom.xml new file mode 100644 index 000000000..5f5fee9fc --- /dev/null +++ b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/child-one/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + + + localhost + it-property-updates-aggregate-report-333 + 1.0 + + + localhost + it-property-updates-aggregate-report-333-child-one + 1.0 + jar + dependency-updates-report + http://localhost/ + + + 1.1.1.1 + + + diff --git a/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/child-two/pom.xml b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/child-two/pom.xml new file mode 100644 index 000000000..843a9253a --- /dev/null +++ b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/child-two/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + + + localhost + it-property-updates-aggregate-report-333 + 1.0 + + + localhost + it-property-updates-aggregate-report-333-child-two + 1.0 + jar + dependency-updates-report + http://localhost/ + + diff --git a/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/invoker.properties b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/invoker.properties new file mode 100644 index 000000000..c01f7db0e --- /dev/null +++ b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/invoker.properties @@ -0,0 +1 @@ +invoker.goals=site diff --git a/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/pom.xml b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/pom.xml new file mode 100644 index 000000000..8d4b029b5 --- /dev/null +++ b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + + + localhost + dummy-aggregate-child + 1.0.1-SNAPSHOT + + + localhost + it-property-updates-aggregate-report-333 + 1.0 + pom + http://localhost/ + + + 2.12.0.0 + + + + + + + maven-site-plugin + @sitePluginVersion@ + + + + + + + + test.bigversion + dummy-lib + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + false + + + + property-updates-aggregate-report + + + + + + + + + child-one + child-two + + diff --git a/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/src/site/site.xml b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/src/site/site.xml new file mode 100644 index 000000000..e95514848 --- /dev/null +++ b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/src/site/site.xml @@ -0,0 +1,7 @@ + + + org.apache.maven.skins + maven-default-skin + 1.0 + + diff --git a/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/verify.groovy b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/verify.groovy new file mode 100644 index 000000000..bd1522b84 --- /dev/null +++ b/versions-maven-plugin/src/it/it-property-updates-aggregate-report-issue-333/verify.groovy @@ -0,0 +1,7 @@ +output = new File( basedir, 'target/site/property-updates-aggregate-report.html' ).text + .replaceAll( '<[^>]+>', ' ' ) + .replaceAll( '&[^;]+;', ' ' ) + .replaceAll( '\\s+', ' ' ) + +assert ( output =~ '\\$\\{version.dummy-lib} 1.1.1.1' ) +assert ( output =~ '\\$\\{version.dummy-lib} 2.12.0.0' ) diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractDependencyUpdatesReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractDependencyUpdatesReportMojo.java new file mode 100644 index 000000000..d183fbdb2 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractDependencyUpdatesReportMojo.java @@ -0,0 +1,365 @@ +package org.codehaus.mojo.versions; + +/* + * 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 static java.util.Collections.emptyMap; +import static org.codehaus.mojo.versions.utils.MavenProjectUtils.interpolateVersion; +import static org.codehaus.mojo.versions.utils.MiscUtils.filter; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.MavenReportException; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.wagon.Wagon; +import org.codehaus.mojo.versions.api.ArtifactVersions; +import org.codehaus.mojo.versions.api.VersionRetrievalException; +import org.codehaus.mojo.versions.reporting.ReportRendererFactory; +import org.codehaus.mojo.versions.reporting.model.DependencyUpdatesModel; +import org.codehaus.mojo.versions.utils.DependencyComparator; +import org.codehaus.mojo.versions.xml.DependencyUpdatesXmlReportRenderer; +import org.codehaus.plexus.i18n.I18N; + +/** + * Generates a report of available updates for the dependencies of a project. + */ +public abstract class AbstractDependencyUpdatesReportMojo extends AbstractVersionsReport +{ + + private static final DependencyComparator DEPENDENCY_COMPARATOR = DependencyComparator.INSTANCE; + + /** + * Whether to process the dependencyManagement in pom or not. + * + * @since 2.5 + */ + @Parameter( property = "processDependencyManagement", defaultValue = "true" ) + protected boolean processDependencyManagement; + + /** + * Whether to process the dependencyManagement part transitive or not. + * In case of <type>pom</type>and + * <scope>import</scope> this means + * by default to report also the imported dependencies. + * If processTransitive is set to false the report will only show + * updates of the imported pom itself. + * + * @since 2.5 Note: Currently in experimental state. + */ + @Parameter( property = "processDependencyManagementTransitive", defaultValue = "true" ) + protected boolean processDependencyManagementTransitive; + + /** + * Report formats (html and/or xml). HTML by default. + */ + @Parameter( property = "dependencyUpdatesReportFormats", defaultValue = "html" ) + protected String[] formats = new String[] {"html"}; + + /** + * If true, only shows the subsection of the dependencyManagement artifacts that + * are actually used in the project's dependency graph. false by default. + * + * @since 2.12 + */ + @Parameter( property = "onlyProjectDependencies", defaultValue = "false" ) + protected boolean onlyProjectDependencies; + + /** + * If true, only shows upgradable dependencies in the report. false by default. + * + * @since 2.12 + */ + @Parameter( property = "onlyUpgradable", defaultValue = "false" ) + protected boolean onlyUpgradable; + + public AbstractDependencyUpdatesReportMojo( I18N i18n, + RepositorySystem repositorySystem, + org.eclipse.aether.RepositorySystem aetherRepositorySystem, + Map wagonMap, + ReportRendererFactory rendererFactory ) + { + super( i18n, repositorySystem, aetherRepositorySystem, wagonMap, rendererFactory ); + } + + /** + * {@inheritDoc} + */ + public boolean isExternalReport() + { + return false; + } + + /** + * {@inheritDoc} + */ + public boolean canGenerateReport() + { + return true; + } + + /** + * generates an empty report in case there are no sources to generate a report with + * + * @param locale the locale to generate the report for. + * @param sink the report formatting tool + */ + @SuppressWarnings( "deprecation" ) + protected void doGenerateReport( Locale locale, Sink sink ) throws MavenReportException + { + + Set dependencies = getDependencies(); + + Set dependencyManagement; + + if ( processDependencyManagement ) + { + dependencyManagement = getDependencyManagement( dependencies ); + handleOnlyProjectDependencies( dependencyManagement, dependencies ); + } + else + { + dependencyManagement = Collections.emptySet(); + } + + try + { + + Map dependencyUpdates = + getHelper().lookupDependenciesUpdates( dependencies, false ); + + Map dependencyManagementUpdates = + processDependencyManagement ? getHelper().lookupDependenciesUpdates( dependencyManagement, false ) + : emptyMap(); + + if ( onlyUpgradable ) + { + dependencyUpdates = filter( dependencyUpdates, e -> e.getVersions().length > 0 ); + dependencyManagementUpdates = filter( dependencyManagementUpdates, e -> e.getVersions().length > 0 ); + } + + if ( getLog().isDebugEnabled() ) + { + getLog().debug( "Dependency versions:" ); + dependencyUpdates.forEach( ( key, value ) -> getLog().debug( + key.toString() + ": " + Arrays.stream( value.getVersions() ) + .map( ArtifactVersion::toString ) + .collect( Collectors.joining( ", " ) ) ) ); + + getLog().debug( "Dependency management versions:" ); + dependencyManagementUpdates.forEach( ( key, value ) -> getLog().debug( + key.toString() + ": " + Arrays.stream( value.getVersions() ) + .map( ArtifactVersion::toString ) + .collect( Collectors.joining( ", " ) ) ) ); + } + + DependencyUpdatesModel model = new DependencyUpdatesModel( dependencyUpdates, dependencyManagementUpdates ); + + renderReport( locale, sink, model ); + } + catch ( VersionRetrievalException e ) + { + throw new RuntimeException( e ); + } + } + + protected void handleDependencyManagementTransitive( MavenProject project, + Set dependencyManagementCollector ) + throws MavenReportException + { + if ( processDependencyManagementTransitive ) + { + if ( hasDependencyManagement( project ) ) + { + for ( Dependency dep : project.getDependencyManagement().getDependencies() ) + { + getLog().debug( + "Dpmg: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getVersion() + ":" + + dep.getType() + ":" + dep.getScope() ); + } + dependencyManagementCollector.addAll( project.getDependencyManagement().getDependencies() ); + } + } + else + { + if ( project.getOriginalModel().getDependencyManagement() != null + && project.getOriginalModel().getDependencyManagement().getDependencies() != null ) + { + // Using the original model to get the original dependencyManagement entries and + // not the interpolated model. + // TODO: I'm not 100% sure if this will work correctly in all cases. + for ( Dependency dep : project.getOriginalModel().getDependencyManagement().getDependencies() ) + { + dep = interpolateVersion( dep, project ); + + getLog().debug( "Original Dpmg: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + + dep.getVersion() + ":" + dep.getType() + ":" + dep.getScope() ); + } + dependencyManagementCollector.addAll( + project.getOriginalModel().getDependencyManagement().getDependencies() ); + } + } + } + + private void handleOnlyProjectDependencies( Set dependencyManagement, + Set dependencies ) + { + if ( !onlyProjectDependencies ) + { + // Retains only dependencies not present in dependencyManagement + dependencies.removeIf( dep -> dependencyManagement.stream().anyMatch( dmDep -> match( dep, dmDep ) ) ); + } + else + { + // Retain only dependencies in dependencyManagement that are also present in dependencies + dependencyManagement.removeIf( dep -> dependencies.stream().noneMatch( dmDep -> match( dep, dmDep ) ) ); + } + } + + /** + * Constructs a final instance of a {@link Set} with a {@link DependencyComparator} comparator. + * This set can be further populated by implementations, and should contain dependencies, that are present + * in projects direct dependencies section. + * + * @return a {@link Set} that can be additionally populated by {@link #populateDependencies(Set)}. + * If not, an empty set is returned + * */ + private Set getDependencies() + { + final Set dependenciesCollector = new TreeSet<>( DEPENDENCY_COMPARATOR ); + populateDependencies( dependenciesCollector ); + return dependenciesCollector; + } + + /** + * Implementations of {@link AbstractDependencyUpdatesReportMojo} may use this to supply the main processing logic + * (see {@link #getDependencyManagement(Set)}) with desired dependency data, which will be used + * in the creation of the report. + * + * @param dependenciesCollector, a Set, initialized with a DependencyComparator + * comparator. + * */ + protected abstract void populateDependencies( Set dependenciesCollector ); + + /** + * Constructs a final instance of a {@link Set} with a {@link DependencyComparator} comparator. + * This set can be further populated by implementations, and should contain dependencies, that are present + * in projects dependencyManagement section. + * + * @return a {@link Set} that can be additionally populated by + * {@link #populateDependencyManagement(Set, Set)}. If not, an empty set is returned + * */ + private Set getDependencyManagement( Set dependencies ) throws MavenReportException + { + final Set dependencyManagementCollector = new TreeSet<>( DEPENDENCY_COMPARATOR ); + populateDependencyManagement ( dependencyManagementCollector, dependencies ); + return dependencyManagementCollector; + } + + /** + * Implementations of {@link AbstractDependencyUpdatesReportMojo} may use this to supply the main processing logic + * (see {@link #getDependencyManagement(Set)}) with desired managed dependencies data, which will be used + * in the creation of the report. + * + * @param dependencyManagementCollector, a Set initialized with a DependencyComparator + * @param dependencies an already populated set of dependencies(non-managed) + * comparator. + * + * @throws MavenReportException when things go wrong. + * */ + protected abstract void populateDependencyManagement( Set dependencyManagementCollector, + Set dependencies ) + throws MavenReportException; + + private void renderReport( Locale locale, + Sink sink, + DependencyUpdatesModel model ) + throws MavenReportException + { + for ( String format : formats ) + { + if ( "html".equals( format ) ) + { + rendererFactory.createReportRenderer( getOutputName(), sink, locale, model ).render(); + } + else if ( "xml".equals( format ) ) + { + Path outputDir = Paths.get( getProject().getBuild().getDirectory() ); + if ( !Files.exists( outputDir ) ) + { + try + { + Files.createDirectories( outputDir ); + } + catch ( IOException e ) + { + throw new MavenReportException( "Could not create the output directory" ); + } + } + Path outputFile = outputDir.resolve( getOutputName() + ".xml" ); + new DependencyUpdatesXmlReportRenderer( model, outputFile ).render(); + } + } + } + + /** + * Compares two dependencies with each other + * + * @return true if the two dependencies match + */ + private boolean match( Dependency dep, Dependency dmDep ) + { + return dmDep.getGroupId().equals( dep.getGroupId() ) + && dmDep.getArtifactId().equals( dep.getArtifactId() ) + && ( dmDep.getScope() == null || dmDep.getScope().equals( dep.getScope() ) ) + && ( dmDep.getClassifier() == null || dmDep.getClassifier().equals( dep.getClassifier() ) ) + && ( dep.getVersion() == null || dmDep.getVersion() == null || dmDep.getVersion() + .equals( dep.getVersion() ) ); + } + + protected boolean hasDependencyManagement( MavenProject project ) + { + if ( project == null ) + { + return false; + } + return project.getDependencyManagement() != null + && project.getDependencyManagement().getDependencies() != null; + } + + /** + * {@inheritDoc} + */ + public String getOutputName() + { + return "dependency-updates-report"; + } +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPluginUpdatesReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPluginUpdatesReportMojo.java new file mode 100644 index 000000000..36ed84d9f --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPluginUpdatesReportMojo.java @@ -0,0 +1,249 @@ +package org.codehaus.mojo.versions; + +/* + * 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 static org.codehaus.mojo.versions.utils.MiscUtils.filter; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.MavenReportException; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.wagon.Wagon; +import org.codehaus.mojo.versions.api.PluginUpdatesDetails; +import org.codehaus.mojo.versions.api.VersionRetrievalException; +import org.codehaus.mojo.versions.reporting.ReportRendererFactory; +import org.codehaus.mojo.versions.reporting.model.PluginUpdatesModel; +import org.codehaus.mojo.versions.utils.PluginComparator; +import org.codehaus.mojo.versions.xml.PluginUpdatesXmlReportRenderer; +import org.codehaus.plexus.i18n.I18N; + +/** + * Generates a report of available updates for the plugins of a project. + */ + +public abstract class AbstractPluginUpdatesReportMojo extends AbstractVersionsReport +{ + + private static final PluginComparator PLUGIN_COMPARATOR = PluginComparator.INSTANCE; + + /** + * Report formats (html and/or xml). HTML by default. + */ + @Parameter( property = "pluginUpdatesReportFormats", defaultValue = "html" ) + private String[] formats = new String[] { "html" }; + + /** + * If true, only shows the subsection of the pluginManagement artifacts that + * are actually used in the project's plugin graph. false by default. + * + * @since 2.12 + */ + @Parameter( property = "onlyProjectPlugins", defaultValue = "false" ) + protected boolean onlyProjectPlugins; + + /** + * If true, only shows upgradable plugins in the report. false by default. + * + * @since 2.12 + */ + @Parameter( property = "onlyUpgradable", defaultValue = "false" ) + protected boolean onlyUpgradable; + + public AbstractPluginUpdatesReportMojo( I18N i18n, + RepositorySystem repositorySystem, + org.eclipse.aether.RepositorySystem aetherRepositorySystem, + Map wagonMap, + ReportRendererFactory rendererFactory ) + { + super( i18n, repositorySystem, aetherRepositorySystem, wagonMap, rendererFactory ); + } + + /** + * {@inheritDoc} + */ + public boolean isExternalReport() + { + return false; + } + + /** + * {@inheritDoc} + */ + public boolean canGenerateReport() + { + return haveBuildPlugins( getProject() ) || haveBuildPluginManagementPlugins( getProject() ); + } + + protected boolean haveBuildPluginManagementPlugins( MavenProject project ) + { + return project.getBuild() != null && project.getBuild().getPluginManagement() != null + && project.getBuild().getPluginManagement().getPlugins() != null && !project.getBuild() + .getPluginManagement().getPlugins().isEmpty(); + } + + protected boolean haveBuildPlugins( MavenProject project ) + { + return project.getBuild() != null && project.getBuild().getPlugins() != null + && !project.getBuild().getPlugins().isEmpty(); + } + + /** + * generates an empty report in case there are no sources to generate a report with + * + * @param locale the locale to generate the report for. + * @param sink the report formatting tool + */ + protected void doGenerateReport( Locale locale, Sink sink ) throws MavenReportException + { + + Set pluginManagement = getPluginManagement(); + + Set plugins = getPlugins(); + + handleOnlyProjectPlugins( pluginManagement, plugins ); + + try + { + + Map pluginUpdates = + getHelper().lookupPluginsUpdates( plugins, getAllowSnapshots() ); + Map pluginManagementUpdates = + getHelper().lookupPluginsUpdates( pluginManagement, getAllowSnapshots() ); + + if ( onlyUpgradable ) + { + pluginUpdates = filter( pluginUpdates, p -> p.getVersions().length > 0 ); + pluginManagementUpdates = filter( pluginManagementUpdates, p -> p.getVersions().length > 0 ); + } + + renderReport( locale, sink, new PluginUpdatesModel( pluginUpdates, pluginManagementUpdates ) ); + } + catch ( VersionRetrievalException e ) + { + throw new MavenReportException( e.getMessage(), e ); + } + } + + /** + * Constructs a instance of a {@link Set} with a {@link PluginComparator} comparator. This set can be + * further populated by implementations and should contain plugins, that are present in projects pluginManagement + * section. + * + * @return a {@link Set} that can be additionally populated by {@link #populatePluginManagement(Set)}}. + * If not, an empty set is returned + * */ + private Set getPluginManagement() + { + final Set pluginManagementCollector = new TreeSet<>( PLUGIN_COMPARATOR ); + populatePluginManagement( pluginManagementCollector ); + return pluginManagementCollector; + } + + /** + * Implementations of {@link AbstractPluginUpdatesReportMojo} may use this to supply the main processing logic + * with desired pluginManagement data, which will be used in the creation of the report. + * + * @param pluginManagementCollector, a set initialized with a {@link PluginComparator} comparator. + * */ + protected abstract void populatePluginManagement( Set pluginManagementCollector ); + + + /** + * Constructs a final instance of a {@link Set} with a {@link PluginComparator} comparator. This set can be + * further populated by implementations, and should contain plugins, that are present in projects build section. + * + * @return a {@link Set} that can be additionally populated by {@link #populatePlugins(Set)}. + * If not, an empty set is returned + * */ + private Set getPlugins() + { + final Set pluginsCollector = new TreeSet<>( PLUGIN_COMPARATOR ); + populatePlugins( pluginsCollector ); + return pluginsCollector; + } + + /** + * Implementations of {@link AbstractPluginUpdatesReportMojo} may use this to supply the main processing logic + * with desired build plugin information, which will be used to create the report. + * + *@param pluginsCollector, a set initialized with a {@link PluginComparator} comparator. + * */ + protected abstract void populatePlugins( Set pluginsCollector ); + + private void renderReport( Locale locale, Sink sink, PluginUpdatesModel model ) + throws MavenReportException + { + for ( String format : formats ) + { + if ( "html".equals( format ) ) + { + rendererFactory.createReportRenderer( getOutputName(), sink, locale, model ).render(); + } + else if ( "xml".equals( format ) ) + { + Path outputDir = Paths.get( getProject().getBuild().getDirectory() ); + if ( !Files.exists( outputDir ) ) + { + try + { + Files.createDirectories( outputDir ); + } + catch ( IOException e ) + { + throw new MavenReportException( "Could not create the output directory" ); + } + } + Path outputFile = outputDir.resolve( getOutputName() + ".xml" ); + new PluginUpdatesXmlReportRenderer( model, outputFile ).render(); + } + } + } + + private void handleOnlyProjectPlugins( Set pluginManagement, Set plugins ) + { + + if ( !onlyProjectPlugins ) + { + // Retains only plugins not present in pluginManagement + plugins.removeIf( plugin -> pluginManagement.stream() + .anyMatch( pmPlugin -> PLUGIN_COMPARATOR.compare( plugin, pmPlugin ) == 0 ) ); + } + else + { + // Retain only plugins in pluginManagement that are also present in plugins + pluginManagement.removeIf( + pmPlugin -> plugins.stream() + .noneMatch( plugin -> PLUGIN_COMPARATOR.compare( plugin, pmPlugin ) == 0 ) ); + } + } + + /** + * {@inheritDoc} + */ + public abstract String getOutputName(); +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPropertyUpdatesReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPropertyUpdatesReportMojo.java new file mode 100644 index 000000000..0380369d0 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPropertyUpdatesReportMojo.java @@ -0,0 +1,218 @@ +package org.codehaus.mojo.versions; + +/* + * 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 java.nio.file.Paths; +import java.util.Locale; +import java.util.Map; +import java.util.TreeMap; +import org.apache.maven.doxia.sink.Sink; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.MavenReportException; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.wagon.Wagon; +import org.codehaus.mojo.versions.api.Property; +import org.codehaus.mojo.versions.api.PropertyVersions; +import org.codehaus.mojo.versions.api.VersionsHelper.VersionPropertiesMapRequest; +import org.codehaus.mojo.versions.reporting.ReportRendererFactory; +import org.codehaus.mojo.versions.reporting.model.PropertyUpdatesModel; +import org.codehaus.mojo.versions.utils.PropertyComparator; +import org.codehaus.mojo.versions.xml.PropertyUpdatesXmlReportRenderer; +import org.codehaus.plexus.i18n.I18N; + +/** + * Generates a report of available updates for properties of a project which are linked to the dependencies and/or + * plugins of a project. + */ +public abstract class AbstractPropertyUpdatesReportMojo extends AbstractVersionsReport +{ + + + private static final PropertyComparator PROPERTIES_COMPARATOR = PropertyComparator.INSTANCE; + + /** + * Any restrictions that apply to specific properties. + * + * @since 1.0-beta-1 + */ + @Parameter + private Property[] properties; + + /** + * A comma separated list of properties to include in the report. + * + * @since 1.0-beta-1 + */ + @Parameter( property = "includeProperties" ) + private String includeProperties = null; + + /** + * A comma separated list of properties to not include in the report. + * + * @since 1.0-beta-1 + */ + @Parameter( property = "excludeProperties" ) + private String excludeProperties = null; + + /** + * Whether properties linking versions should be auto-detected or not. + * + * @since 1.0-beta-1 + */ + @Parameter( property = "autoLinkItems", defaultValue = "true" ) + private boolean autoLinkItems; + + /** + *

Whether to include property updates from parent.

+ * + * @since 2.14.0 + */ + @Parameter( property = "includeParent", defaultValue = "true" ) + private boolean includeParent = true; + + /** + * Report formats (html and/or xml). HTML by default. + * + * @since 2.14.0 + */ + @Parameter( property = "propertyUpdatesReportFormats", defaultValue = "html" ) + protected String[] formats = new String[] {"html"}; + + public AbstractPropertyUpdatesReportMojo( I18N i18n, + RepositorySystem repositorySystem, + org.eclipse.aether.RepositorySystem aetherRepositorySystem, + Map wagonMap, + ReportRendererFactory rendererFactory ) + { + super( i18n, repositorySystem, aetherRepositorySystem, wagonMap, rendererFactory ); + } + + /** + * {@inheritDoc} + */ + public boolean isExternalReport() + { + return false; + } + + /** + * {@inheritDoc} + */ + public boolean canGenerateReport() + { + return haveBuildProperties(); + } + + protected boolean haveBuildProperties() + { + return getProject().getProperties() != null && !getProject().getProperties().isEmpty(); + } + + protected void doGenerateReport( Locale locale, Sink sink ) + throws MavenReportException + { + try + { + final Map updateSet = new TreeMap<>( PROPERTIES_COMPARATOR ); + populateUpdateSet( updateSet ); + + renderReport( locale, + sink, + getPropertyUpdatesModel( updateSet ) ); + } + catch ( MojoExecutionException e ) + { + throw new MavenReportException( e.getMessage(), e ); + } + + } + + /** + * Method used to supply {@link PropertyUpdatesModel} with data about updated properties. + * + * @param propertyCollector map for collecting properties in implementations + * + * @throws MavenReportException when things go wrong. + * @throws MojoExecutionException if something goes wrong. + * */ + protected abstract void populateUpdateSet( + Map propertyCollector ) + throws MojoExecutionException, MavenReportException; + + + private void renderReport( Locale locale, Sink sink, PropertyUpdatesModel propertyUpdatesModel ) + throws MavenReportException + { + + for ( String format : this.formats ) + { + if ( "html".equals( format ) ) + { + this.rendererFactory.createReportRenderer( getOutputName(), sink, locale, propertyUpdatesModel ) + .render(); + } + else if ( "xml".equals( format ) ) + { + Path outputDir = Paths.get( getProject().getBuild().getDirectory() ); + if ( !Files.exists( outputDir ) ) + { + try + { + Files.createDirectories( outputDir ); + } + catch ( IOException e ) + { + throw new MavenReportException( "Could not create the output directory" ); + } + } + Path outputFile = outputDir.resolve( getOutputName() + ".xml" ); + new PropertyUpdatesXmlReportRenderer( propertyUpdatesModel, outputFile ).render(); + } + } + } + + private PropertyUpdatesModel getPropertyUpdatesModel( Map updateSet ) + { + return new PropertyUpdatesModel( PROPERTIES_COMPARATOR, updateSet ); + } + + protected VersionPropertiesMapRequest getRequest( MavenProject project ) + { + return VersionPropertiesMapRequest.builder() + .withMavenProject( project ) + .withPropertyDefinitions( this.properties ) + .withIncludeProperties( this.includeProperties ) + .withExcludeProperties( this.excludeProperties ) + .withIncludeParent( this.includeParent ) + .withAutoLinkItems( this.autoLinkItems ) + .build(); + } + + /** + * {@inheritDoc} + */ + public String getOutputName() + { + return "property-updates-report"; + } +} 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 92021ba27..c97b653ce 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 @@ -537,6 +537,7 @@ else if ( PomHelper.setPropertyVersion( pom, version.getProfileId(), property.ge * Configure and return the change recorder. * * @return The change recorder + * @throws MojoExecutionException if something goes wrong. */ protected ChangeRecorder getChangeRecorder() throws MojoExecutionException { @@ -553,6 +554,7 @@ protected ChangeRecorder getChangeRecorder() throws MojoExecutionException * Save all of the changes recorded by the change recorder. * * @throws IOException On I/O errors + * @throws MojoExecutionException if something goes wrong. */ protected void saveChangeRecorderResults() throws IOException, MojoExecutionException diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesAggregateReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesAggregateReportMojo.java new file mode 100644 index 000000000..63b07f851 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesAggregateReportMojo.java @@ -0,0 +1,92 @@ +package org.codehaus.mojo.versions; + +/* + * 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.util.Map; +import java.util.Set; +import javax.inject.Inject; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.MavenReportException; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.wagon.Wagon; +import org.codehaus.mojo.versions.reporting.ReportRendererFactory; +import org.codehaus.mojo.versions.reporting.util.AggregateReportUtils; +import org.codehaus.plexus.i18n.I18N; + +/** + * Generates an aggregate report of available updates for the dependencies of a project. + * + * @since 2.14.0 + */ +@Mojo( name = "dependency-updates-aggregate-report", + requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true, aggregator = true ) +public class DependencyUpdatesAggregateReportMojo extends AbstractDependencyUpdatesReportMojo +{ + + @Inject + protected DependencyUpdatesAggregateReportMojo( I18N i18n, RepositorySystem repositorySystem, + org.eclipse.aether.RepositorySystem aetherRepositorySystem, + Map wagonMap, + ReportRendererFactory rendererFactory ) + { + super( i18n, repositorySystem, aetherRepositorySystem, wagonMap, rendererFactory ); + } + + /** + * {@inheritDoc} + * */ + @Override + protected void populateDependencies( Set dependenciesCollector ) + { + getLog().debug( String.format( "Collecting dependencies for project %s", + project.getName() ) ); + for ( MavenProject project : AggregateReportUtils.getProjectsToProcess( getProject() ) ) + { + dependenciesCollector.addAll( project.getDependencies() ); + } + } + + /** + * {@inheritDoc} + * */ + @Override + protected void populateDependencyManagement( Set dependencyManagementCollector, + Set dependencies ) throws MavenReportException + { + for ( MavenProject project : AggregateReportUtils.getProjectsToProcess( getProject() ) ) + { + getLog().debug( String.format( "Collecting managed dependencies for project %s", + project.getName() ) ); + handleDependencyManagementTransitive( project, dependencyManagementCollector ); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String getOutputName() + { + return "dependency-updates-aggregate-report"; + } + +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java index 8eb146ea6..711086ccb 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReportMojo.java @@ -19,40 +19,18 @@ * under the License. */ -import javax.inject.Inject; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.TreeSet; -import java.util.stream.Collectors; - -import org.apache.maven.artifact.versioning.ArtifactVersion; -import org.apache.maven.doxia.sink.Sink; +import javax.inject.Inject; import org.apache.maven.model.Dependency; import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.reporting.MavenReportException; import org.apache.maven.repository.RepositorySystem; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.ArtifactVersions; -import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.reporting.ReportRendererFactory; -import org.codehaus.mojo.versions.reporting.model.DependencyUpdatesModel; -import org.codehaus.mojo.versions.utils.DependencyComparator; -import org.codehaus.mojo.versions.xml.DependencyUpdatesXmlReportRenderer; import org.codehaus.plexus.i18n.I18N; -import static java.util.Collections.emptyMap; -import static org.codehaus.mojo.versions.utils.MavenProjectUtils.interpolateVersion; -import static org.codehaus.mojo.versions.utils.MiscUtils.filter; - /** * Generates a report of available updates for the dependencies of a project. * @@ -61,53 +39,9 @@ */ @Mojo( name = "dependency-updates-report", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true ) -public class DependencyUpdatesReportMojo extends AbstractVersionsReport +public class DependencyUpdatesReportMojo extends AbstractDependencyUpdatesReportMojo { - /** - * Whether to process the dependencyManagement in pom or not. - * - * @since 2.5 - */ - @Parameter( property = "processDependencyManagement", defaultValue = "true" ) - protected boolean processDependencyManagement; - - /** - * Whether to process the dependencyManagement part transitive or not. - * In case of <type>pom</type>and - * <scope>import</scope> this means - * by default to report also the imported dependencies. - * If processTransitive is set to false the report will only show - * updates of the imported pom itself. - * - * @since 2.5 Note: Currently in experimental state. - */ - @Parameter( property = "processDependencyManagementTransitive", defaultValue = "true" ) - protected boolean processDependencyManagementTransitive; - - /** - * Report formats (html and/or xml). HTML by default. - */ - @Parameter( property = "dependencyUpdatesReportFormats", defaultValue = "html" ) - protected String[] formats = new String[] {"html"}; - - /** - * If true, only shows the subsection of the dependencyManagement artifacts that - * are actually used in the project's dependency graph. false by default. - * - * @since 2.12 - */ - @Parameter( property = "onlyProjectDependencies", defaultValue = "false" ) - protected boolean onlyProjectDependencies; - - /** - * If true, only shows upgradable dependencies in the report. false by default. - * - * @since 2.12 - */ - @Parameter( property = "onlyUpgradable", defaultValue = "false" ) - protected boolean onlyUpgradable; - @Inject protected DependencyUpdatesReportMojo( I18N i18n, RepositorySystem repositorySystem, org.eclipse.aether.RepositorySystem aetherRepositorySystem, @@ -119,157 +53,30 @@ protected DependencyUpdatesReportMojo( I18N i18n, RepositorySystem repositorySys /** * {@inheritDoc} - */ - public boolean isExternalReport() + * */ + @Override + protected void populateDependencies( Set dependenciesCollector ) { - return false; + getLog().debug( String.format( "Collecting dependencies for project %s", + getProject().getName() ) ); + dependenciesCollector.addAll( getProject().getDependencies() ); } /** * {@inheritDoc} - */ - public boolean canGenerateReport() + * */ + @Override + protected void populateDependencyManagement( Set dependencyManagementCollector, + Set dependencies ) throws MavenReportException { - return true; - } - - /** - * generates an empty report in case there are no sources to generate a report with - * - * @param locale the locale to generate the report for. - * @param sink the report formatting tool - */ - @SuppressWarnings( "deprecation" ) - protected void doGenerateReport( Locale locale, Sink sink ) throws MavenReportException - { - Set dependencies = new TreeSet<>( DependencyComparator.INSTANCE ); - dependencies.addAll( getProject().getDependencies() ); - - Set dependencyManagement = new TreeSet<>( DependencyComparator.INSTANCE ); - - if ( processDependencyManagement ) + if ( hasDependencyManagement( getProject() ) ) { - if ( processDependencyManagementTransitive ) - { - if ( getProject().getDependencyManagement() != null - && getProject().getDependencyManagement().getDependencies() != null ) - { - for ( Dependency dep : getProject().getDependencyManagement().getDependencies() ) - { - getLog().debug( - "Dpmg: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getVersion() + ":" - + dep.getType() + ":" + dep.getScope() ); - } - dependencyManagement.addAll( getProject().getDependencyManagement().getDependencies() ); - } - } - else - { - if ( getProject().getOriginalModel().getDependencyManagement() != null - && getProject().getOriginalModel().getDependencyManagement().getDependencies() != null ) - { - // Using the original model to get the original dependencyManagement entries and - // not the interpolated model. - // TODO: I'm not 100% sure if this will work correctly in all cases. - for ( Dependency dep : getProject().getOriginalModel().getDependencyManagement().getDependencies() ) - { - dep = interpolateVersion( dep, getProject() ); - - getLog().debug( "Original Dpmg: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" - + dep.getVersion() + ":" + dep.getType() + ":" + dep.getScope() ); - } - dependencyManagement.addAll( - getProject().getOriginalModel().getDependencyManagement().getDependencies() ); - } - } - - if ( !onlyProjectDependencies ) - { - // Retains only dependencies not present in dependencyManagement - dependencies.removeIf( dep -> dependencyManagement.stream().anyMatch( dmDep -> match( dep, dmDep ) ) ); - } - else - { - // Retain only dependencies in dependencyManagement that are also present in dependencies - dependencyManagement.removeIf( dep -> dependencies.stream().noneMatch( dmDep -> match( dep, dmDep ) ) ); - } - } - - try - { - Map dependencyUpdates = - getHelper().lookupDependenciesUpdates( dependencies, false ); - - Map dependencyManagementUpdates = - processDependencyManagement ? getHelper().lookupDependenciesUpdates( dependencyManagement, false ) - : emptyMap(); - - if ( onlyUpgradable ) - { - dependencyUpdates = filter( dependencyUpdates, e -> e.getVersions().length > 0 ); - dependencyManagementUpdates = filter( dependencyManagementUpdates, e -> e.getVersions().length > 0 ); - } - - if ( getLog().isDebugEnabled() ) - { - getLog().debug( "Dependency versions:" ); - dependencyUpdates.forEach( ( key, value ) -> getLog().debug( key.toString() + ": " - + Arrays.stream( value.getVersions() ).map( ArtifactVersion::toString ) - .collect( Collectors.joining( ", " ) ) ) ); - - getLog().debug( "Dependency management versions:" ); - dependencyManagementUpdates.forEach( ( key, value ) -> getLog().debug( key.toString() + ": " - + Arrays.stream( value.getVersions() ).map( ArtifactVersion::toString ) - .collect( Collectors.joining( ", " ) ) ) ); - } - - DependencyUpdatesModel model = new DependencyUpdatesModel( dependencyUpdates, dependencyManagementUpdates ); - for ( String format : formats ) - { - if ( "html".equals( format ) ) - { - rendererFactory.createReportRenderer( getOutputName(), sink, locale, model ).render(); - } - else if ( "xml".equals( format ) ) - { - Path outputDir = Paths.get( getProject().getBuild().getDirectory() ); - if ( !Files.exists( outputDir ) ) - { - try - { - Files.createDirectories( outputDir ); - } - catch ( IOException e ) - { - throw new MavenReportException( "Could not create the output directory" ); - } - } - Path outputFile = outputDir.resolve( getOutputName() + ".xml" ); - new DependencyUpdatesXmlReportRenderer( model, outputFile ).render(); - } - } - } - catch ( VersionRetrievalException e ) - { - throw new MavenReportException( e.getMessage(), e ); + getLog().debug( String.format( "Collecting managed dependencies for project %s", + getProject().getName() ) ); + handleDependencyManagementTransitive( getProject(), dependencyManagementCollector ); } } - /** - * Compares two dependencies with each other - * - * @return true if the two dependencies match - */ - private boolean match( Dependency dep, Dependency dmDep ) - { - return dmDep.getGroupId().equals( dep.getGroupId() ) - && dmDep.getArtifactId().equals( dep.getArtifactId() ) - && ( dmDep.getScope() == null || dmDep.getScope().equals( dep.getScope() ) ) - && ( dmDep.getClassifier() == null || dmDep.getClassifier().equals( dep.getClassifier() ) ) - && ( dep.getVersion() == null || dmDep.getVersion() == null || dmDep.getVersion() - .equals( dep.getVersion() ) ); - } - /** * {@inheritDoc} */ @@ -278,4 +85,3 @@ public String getOutputName() return "dependency-updates-report"; } } - diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesAggregateReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesAggregateReportMojo.java new file mode 100644 index 000000000..f9305383b --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesAggregateReportMojo.java @@ -0,0 +1,88 @@ +package org.codehaus.mojo.versions; + +/* + * 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.util.Map; +import java.util.Set; +import javax.inject.Inject; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.wagon.Wagon; +import org.codehaus.mojo.versions.reporting.ReportRendererFactory; +import org.codehaus.mojo.versions.reporting.util.AggregateReportUtils; +import org.codehaus.plexus.i18n.I18N; + +/** + * Generates an aggregated report of available updates for the plugins of a project. + * + * @since 2.14.0 + */ +@Mojo( name = "plugin-updates-aggregate-report", requiresDependencyResolution = ResolutionScope.RUNTIME, + threadSafe = true, aggregator = true ) +public class PluginUpdatesAggregateReportMojo extends AbstractPluginUpdatesReportMojo +{ + + @Inject + protected PluginUpdatesAggregateReportMojo( I18N i18n, RepositorySystem repositorySystem, + org.eclipse.aether.RepositorySystem aetherRepositorySystem, + Map wagonMap, + ReportRendererFactory rendererFactory ) + { + super( i18n, repositorySystem, aetherRepositorySystem, wagonMap, rendererFactory ); + } + + @Override + protected void populatePluginManagement( Set pluginManagementCollector ) + { + for ( MavenProject project : AggregateReportUtils.getProjectsToProcess( getProject() ) ) + { + if ( haveBuildPluginManagementPlugins( project ) ) + { + pluginManagementCollector.addAll( project.getBuild().getPluginManagement().getPlugins() ); + } + } + } + + /** + * {@inheritDoc} + * */ + @Override + protected void populatePlugins( Set pluginsCollector ) + { + for ( MavenProject project : AggregateReportUtils.getProjectsToProcess( getProject() ) ) + { + if ( haveBuildPluginManagementPlugins( project ) ) + { + pluginsCollector.addAll( project.getBuild().getPlugins() ); + } + } + } + + /** + * {@inheritDoc} + */ + public String getOutputName() + { + return "plugin-updates-aggregate-report"; + } + +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReportMojo.java index 7c64b14c8..8eec073c5 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReportMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReportMojo.java @@ -19,35 +19,17 @@ * under the License. */ -import javax.inject.Inject; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.TreeSet; - -import org.apache.maven.doxia.sink.Sink; +import javax.inject.Inject; import org.apache.maven.model.Plugin; import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; -import org.apache.maven.reporting.MavenReportException; import org.apache.maven.repository.RepositorySystem; import org.apache.maven.wagon.Wagon; -import org.codehaus.mojo.versions.api.PluginUpdatesDetails; -import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.reporting.ReportRendererFactory; -import org.codehaus.mojo.versions.reporting.model.PluginUpdatesModel; -import org.codehaus.mojo.versions.utils.PluginComparator; -import org.codehaus.mojo.versions.xml.PluginUpdatesXmlReportRenderer; import org.codehaus.plexus.i18n.I18N; -import static org.codehaus.mojo.versions.utils.MiscUtils.filter; - /** * Generates a report of available updates for the plugins of a project. * @@ -56,32 +38,9 @@ */ @Mojo( name = "plugin-updates-report", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true ) -public class PluginUpdatesReportMojo extends AbstractVersionsReport +public class PluginUpdatesReportMojo extends AbstractPluginUpdatesReportMojo { - /** - * Report formats (html and/or xml). HTML by default. - */ - @Parameter( property = "pluginUpdatesReportFormats", defaultValue = "html" ) - private String[] formats = new String[] { "html" }; - - /** - * If true, only shows the subsection of the pluginManagement artifacts that - * are actually used in the project's plugin graph. false by default. - * - * @since 2.12 - */ - @Parameter( property = "onlyProjectPlugins", defaultValue = "false" ) - protected boolean onlyProjectPlugins; - - /** - * If true, only shows upgradable plugins in the report. false by default. - * - * @since 2.12 - */ - @Parameter( property = "onlyUpgradable", defaultValue = "false" ) - protected boolean onlyUpgradable; - @Inject protected PluginUpdatesReportMojo( I18N i18n, RepositorySystem repositorySystem, @@ -94,109 +53,25 @@ protected PluginUpdatesReportMojo( I18N i18n, /** * {@inheritDoc} - */ - public boolean isExternalReport() + * */ + @Override + protected void populatePluginManagement( Set pluginManagementCollector ) { - return false; + if ( haveBuildPluginManagementPlugins( getProject() ) ) + { + pluginManagementCollector.addAll( getProject().getBuild().getPluginManagement().getPlugins() ); + } } /** * {@inheritDoc} - */ - public boolean canGenerateReport() + * */ + @Override + protected void populatePlugins( Set pluginsCollector ) { - return haveBuildPlugins() || haveBuildPluginManagementPlugins(); - } - - private boolean haveBuildPluginManagementPlugins() - { - return getProject().getBuild() != null && getProject().getBuild().getPluginManagement() != null - && getProject().getBuild().getPluginManagement().getPlugins() != null && !getProject().getBuild() - .getPluginManagement().getPlugins().isEmpty(); - } - - private boolean haveBuildPlugins() - { - return getProject().getBuild() != null && getProject().getBuild().getPlugins() != null - && !getProject().getBuild().getPlugins().isEmpty(); - } - - /** - * generates an empty report in case there are no sources to generate a report with - * - * @param locale the locale to generate the report for. - * @param sink the report formatting tool - */ - protected void doGenerateReport( Locale locale, Sink sink ) throws MavenReportException - { - Set pluginManagement = new TreeSet<>( PluginComparator.INSTANCE ); - if ( haveBuildPluginManagementPlugins() ) - { - pluginManagement.addAll( getProject().getBuild().getPluginManagement().getPlugins() ); - } - - Set plugins = new TreeSet<>( PluginComparator.INSTANCE ); - if ( haveBuildPlugins() ) - { - plugins.addAll( getProject().getBuild().getPlugins() ); - } - - PluginComparator comparator = PluginComparator.INSTANCE; - if ( !onlyProjectPlugins ) - { - // Retains only plugins not present in pluginManagement - plugins.removeIf( plugin -> pluginManagement.stream() - .anyMatch( pmPlugin -> comparator.compare( plugin, pmPlugin ) == 0 ) ); - } - else + if ( haveBuildPlugins( getProject() ) ) { - // Retain only plugins in pluginManagement that are also present in plugins - pluginManagement.removeIf( - pmPlugin -> plugins.stream().noneMatch( plugin -> comparator.compare( plugin, pmPlugin ) == 0 ) ); - } - - try - { - Map pluginUpdates = - getHelper().lookupPluginsUpdates( plugins, getAllowSnapshots() ); - Map pluginManagementUpdates = - getHelper().lookupPluginsUpdates( pluginManagement, getAllowSnapshots() ); - - if ( onlyUpgradable ) - { - pluginUpdates = filter( pluginUpdates, p -> p.getVersions().length > 0 ); - pluginManagementUpdates = filter( pluginManagementUpdates, p -> p.getVersions().length > 0 ); - } - - PluginUpdatesModel model = new PluginUpdatesModel( pluginUpdates, pluginManagementUpdates ); - for ( String format : formats ) - { - if ( "html".equals( format ) ) - { - rendererFactory.createReportRenderer( getOutputName(), getSink(), locale, model ).render(); - } - else if ( "xml".equals( format ) ) - { - Path outputDir = Paths.get( getProject().getBuild().getDirectory() ); - if ( !Files.exists( outputDir ) ) - { - try - { - Files.createDirectories( outputDir ); - } - catch ( IOException e ) - { - throw new MavenReportException( "Could not create the output directory" ); - } - } - Path outputFile = outputDir.resolve( getOutputName() + ".xml" ); - new PluginUpdatesXmlReportRenderer( model, outputFile ).render(); - } - } - } - catch ( VersionRetrievalException e ) - { - throw new MavenReportException( e.getMessage(), e ); + pluginsCollector.addAll( getProject().getBuild().getPlugins() ); } } @@ -208,4 +83,3 @@ public String getOutputName() return "plugin-updates-report"; } } - diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesAggregateReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesAggregateReportMojo.java new file mode 100644 index 000000000..fdb022f74 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesAggregateReportMojo.java @@ -0,0 +1,95 @@ +package org.codehaus.mojo.versions; + +/* + * 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.util.Map; +import javax.inject.Inject; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.apache.maven.reporting.MavenReportException; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.wagon.Wagon; +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.reporting.ReportRendererFactory; +import org.codehaus.mojo.versions.reporting.util.AggregateReportUtils; +import org.codehaus.plexus.i18n.I18N; + +/** + * Generates an aggregate report of available updates for properties of a project which are linked to the dependencies + * and/or plugins of a project. + * + * @since 2.14.0 + */ +@Mojo( name = "property-updates-aggregate-report", requiresDependencyResolution = ResolutionScope.RUNTIME, + threadSafe = true, aggregator = true ) +public class PropertyUpdatesAggregateReportMojo extends AbstractPropertyUpdatesReportMojo +{ + + @Inject + protected PropertyUpdatesAggregateReportMojo( I18N i18n, RepositorySystem repositorySystem, + org.eclipse.aether.RepositorySystem aetherRepositorySystem, + Map wagonMap, + ReportRendererFactory rendererFactory ) + { + super( i18n, repositorySystem, aetherRepositorySystem, wagonMap, rendererFactory ); + } + + /** + * {@inheritDoc} + * */ + @Override + protected void populateUpdateSet( Map propertyCollector ) + throws MojoExecutionException, MavenReportException + { + VersionsHelper helper = getHelper(); + for ( MavenProject project : AggregateReportUtils.getProjectsToProcess( getProject() ) ) + { + propertyCollector.putAll( helper.getVersionPropertiesMap( getRequest( project ) ) ); + } + } + + /** + * {@inheritDoc} + * */ + @Override + protected boolean haveBuildProperties() + { + for ( MavenProject project : AggregateReportUtils.getProjectsToProcess( getProject() ) ) + { + if ( project.getProperties() != null && !project.getProperties().isEmpty() ) + { + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + public String getOutputName() + { + return "property-updates-aggregate-report"; + } +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReportMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReportMojo.java index 8dd941dff..8b6abe85b 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReportMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReportMojo.java @@ -19,31 +19,17 @@ * under the License. */ -import javax.inject.Inject; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Locale; import java.util.Map; -import java.util.TreeMap; - -import org.apache.maven.doxia.sink.Sink; +import javax.inject.Inject; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.reporting.MavenReportException; import org.apache.maven.repository.RepositorySystem; import org.apache.maven.wagon.Wagon; 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.reporting.ReportRendererFactory; -import org.codehaus.mojo.versions.reporting.model.PropertyUpdatesModel; -import org.codehaus.mojo.versions.utils.PropertyComparator; -import org.codehaus.mojo.versions.xml.PropertyUpdatesXmlReportRenderer; import org.codehaus.plexus.i18n.I18N; /** @@ -55,56 +41,8 @@ */ @Mojo( name = "property-updates-report", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true ) -public class PropertyUpdatesReportMojo extends AbstractVersionsReport +public class PropertyUpdatesReportMojo extends AbstractPropertyUpdatesReportMojo { - /** - * Any restrictions that apply to specific properties. - * - * @since 1.0-beta-1 - */ - @Parameter - private Property[] properties; - - /** - * A comma separated list of properties to include in the report. - * - * @since 1.0-beta-1 - */ - @Parameter( property = "includeProperties" ) - private String includeProperties = null; - - /** - * A comma separated list of properties to not include in the report. - * - * @since 1.0-beta-1 - */ - @Parameter( property = "excludeProperties" ) - private String excludeProperties = null; - - /** - * Whether properties linking versions should be auto-detected or not. - * - * @since 1.0-beta-1 - */ - @Parameter( property = "autoLinkItems", defaultValue = "true" ) - private boolean autoLinkItems; - - /** - *

Whether to include property updates from parent. Default: {@code false}

- * - * @since 2.14.0 - */ - @Parameter( property = "includeParent", defaultValue = "false" ) - private boolean includeParent = true; - - /** - * Report formats (html and/or xml). HTML by default. - * - * @since 2.14.0 - */ - @Parameter( property = "propertyUpdatesReportFormats", defaultValue = "html" ) - protected String[] formats = new String[] {"html"}; - @Inject protected PropertyUpdatesReportMojo( I18N i18n, RepositorySystem repositorySystem, @@ -118,68 +56,11 @@ protected PropertyUpdatesReportMojo( I18N i18n, /** * {@inheritDoc} */ - public boolean isExternalReport() + @Override + protected void populateUpdateSet( Map propertyCollector ) + throws MojoExecutionException, MavenReportException { - return false; - } - - /** - * {@inheritDoc} - */ - public boolean canGenerateReport() - { - return haveBuildProperties(); - } - - private boolean haveBuildProperties() - { - return getProject().getProperties() != null && !getProject().getProperties().isEmpty(); - } - - protected void doGenerateReport( Locale locale, Sink sink ) - throws MavenReportException - { - final Map updateSet = new TreeMap<>( PropertyComparator.INSTANCE ); - try - { - updateSet.putAll( getHelper().getVersionPropertiesMap( VersionsHelper.VersionPropertiesMapRequest.builder() - .withMavenProject( getProject() ) - .withPropertyDefinitions( properties ) - .withIncludeProperties( includeProperties ) - .withExcludeProperties( excludeProperties ) - .withIncludeParent( includeParent ) - .withAutoLinkItems( autoLinkItems ) - .build() ) ); - } - catch ( MojoExecutionException e ) - { - throw new MavenReportException( e.getMessage(), e ); - } - PropertyUpdatesModel model = new PropertyUpdatesModel( updateSet ); - for ( String format : formats ) - { - if ( "html".equals( format ) ) - { - rendererFactory.createReportRenderer( getOutputName(), getSink(), locale, model ).render(); - } - else if ( "xml".equals( format ) ) - { - Path outputDir = Paths.get( getProject().getBuild().getDirectory() ); - if ( !Files.exists( outputDir ) ) - { - try - { - Files.createDirectories( outputDir ); - } - catch ( IOException e ) - { - throw new MavenReportException( "Could not create the output directory" ); - } - } - Path outputFile = outputDir.resolve( getOutputName() + ".xml" ); - new PropertyUpdatesXmlReportRenderer( model, outputFile ).render(); - } - } + propertyCollector.putAll( getHelper().getVersionPropertiesMap( getRequest( getProject() ) ) ); } /** @@ -190,4 +71,3 @@ public String getOutputName() return "property-updates-report"; } } - 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 2b95c0f1e..1b76bd9e0 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 @@ -67,6 +67,7 @@ public UseLatestVersionsMojoBase( RepositorySystem repositorySystem, * @param changeKind title for the change recorder records * @param filters optional array of filters * @throws XMLStreamException thrown if the POM update doesn't succeed + * @throws MojoExecutionException if something goes wrong. * @throws VersionRetrievalException thrown if an artifact versions cannot be retrieved */ @SafeVarargs diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java index d1344a811..e66a1ad42 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java @@ -41,8 +41,11 @@ public class ReportRendererFactoryImpl implements ReportRendererFactory { public static final String DEPENDENCY_UPDATES_REPORT = "dependency-updates-report"; + public static final String DEPENDENCY_UPDATES_AGGREGATE_REPORT = "dependency-updates-aggregate-report"; public static final String PLUGIN_UPDATES_REPORT = "plugin-updates-report"; + public static final String PLUGIN_UPDATES_AGGREGATE_REPORT = "plugin-updates-aggregate-report"; public static final String PROPERTY_UPDATES_REPORT = "property-updates-report"; + public static final String PROPERTY_UPDATES_AGGREGATE_REPORT = "property-updates-aggregate-report"; public static final String PARENT_UPDATES_REPORT = "parent-updates-report"; private final I18N i18N; @@ -60,17 +63,18 @@ public ReportRendererFactoryImpl( I18N i18N ) public T createReportRenderer( String reportName, Sink sink, Locale locale, U model ) throws IllegalArgumentException { - if ( DEPENDENCY_UPDATES_REPORT.equals( reportName ) ) + if ( DEPENDENCY_UPDATES_REPORT.equals( reportName ) + || DEPENDENCY_UPDATES_AGGREGATE_REPORT.equals( reportName ) ) { return (T) new DependencyUpdatesReportRenderer<>( i18N, sink, locale, reportName, (DependencyUpdatesModel) model ); } - if ( PLUGIN_UPDATES_REPORT.equals( reportName ) ) + if ( PLUGIN_UPDATES_REPORT.equals( reportName ) || PLUGIN_UPDATES_AGGREGATE_REPORT.equals( reportName ) ) { return (T) new PluginUpdatesReportRenderer( i18N, sink, locale, reportName, (PluginUpdatesModel) model ); } - if ( PROPERTY_UPDATES_REPORT.equals( reportName ) ) + if ( PROPERTY_UPDATES_REPORT.equals( reportName ) || PROPERTY_UPDATES_AGGREGATE_REPORT.equals( reportName ) ) { return (T) new PropertyUpdatesReportRenderer( i18N, sink, locale, reportName, (PropertyUpdatesModel) model ); diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java index c2a6aa460..44058e698 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java @@ -21,7 +21,6 @@ import java.util.Map; import java.util.TreeMap; - import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.PropertyVersions; import org.codehaus.mojo.versions.utils.PropertyComparator; @@ -33,9 +32,9 @@ public class PropertyUpdatesModel { private final Map allUpdates; - public PropertyUpdatesModel( Map propertyUpdates ) + public PropertyUpdatesModel( PropertyComparator comparator, Map propertyUpdates ) { - this.allUpdates = new TreeMap<>( PropertyComparator.INSTANCE ); + this.allUpdates = new TreeMap<>( comparator ); this.allUpdates.putAll( propertyUpdates ); } @@ -43,4 +42,5 @@ public Map getAllUpdates() { return allUpdates; } + } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/util/AggregateReportUtils.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/util/AggregateReportUtils.java new file mode 100644 index 000000000..12ff25b55 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/util/AggregateReportUtils.java @@ -0,0 +1,53 @@ +package org.codehaus.mojo.versions.reporting.util; + +/* + * 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.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.apache.maven.project.MavenProject; + +/** + * Class that contains common aggregate operations + * + * @since 2.14.0 + * */ +public class AggregateReportUtils +{ + + /** + * Returns an aggregated list of {@link MavenProject} for the given project. + * + * @param project to aggregate + * + * @return aggregated list of MavenProject objects for the given project(also containing the project itself) + * */ + public static List getProjectsToProcess( final MavenProject project ) + { + if ( project == null ) + { + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + result.add( project ); + result.addAll( project.getCollectedProjects() ); + return result; + } + +} diff --git a/versions-maven-plugin/src/main/resources/dependency-updates-aggregate-report.properties b/versions-maven-plugin/src/main/resources/dependency-updates-aggregate-report.properties new file mode 100644 index 000000000..5043fdd82 --- /dev/null +++ b/versions-maven-plugin/src/main/resources/dependency-updates-aggregate-report.properties @@ -0,0 +1,55 @@ +# 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. + +report.title=Dependency Updates Aggregate Report +report.description=Provides aggregated details of the dependencies which have updated versions available. +report.overview.title=Overview +report.overview.text=This report summarizes newer versions that may be available for your project's various \ + dependencies. +report.overview.dependencyManagement=Dependency Management +report.overview.noDependencyManagement=This project does not declare any dependencies in a dependencyManagement section. +report.overview.dependency=Dependencies +report.overview.noDependency=This project does not declare any dependencies. +report.overview.numUpToDate=# of dependencies using the latest version available +report.overview.numNewerMajorAvailable=# of dependencies where the next version available is a major version update +report.overview.numNewerMinorAvailable=# of dependencies where the next version available is a minor version update +report.overview.numNewerIncrementalAvailable=# of dependencies where the next version available is an incremental \ + version update +report.overview.numNewerVersionAvailable=# of dependencies where the next version available is smaller than an \ + incremental version update +report.detail.title=Dependency Updates +report.detail.text= +report.status=Status +report.groupId=Group Id +report.artifactId=Artifact Id +report.currentVersion=Current Version +report.scope=Scope +report.classifier=Classifier +report.type=Type +report.latestSubIncremental=Latest Subincremental +report.latestIncremental=Latest Incremental +report.latestMinor=Latest Minor +report.latestMajor=Latest Major +report.updateVersions=Newer versions +report.noUpdatesAvailable=No newer versions available. +report.otherUpdatesAvailable=There is at least one newer version available. +report.incrementalUpdatesAvailable=There is at least one newer incremental version available. \ + Incremental updates are typically passive. +report.minorUpdatesAvailable=There is at least one newer minor version available. \ + Minor updates are sometimes passive. +report.majorUpdatesAvailable=There is at least one newer major version available. \ + Major updates are rarely passive. diff --git a/versions-maven-plugin/src/main/resources/plugin-updates-aggregate-report.properties b/versions-maven-plugin/src/main/resources/plugin-updates-aggregate-report.properties new file mode 100644 index 000000000..9d47f004b --- /dev/null +++ b/versions-maven-plugin/src/main/resources/plugin-updates-aggregate-report.properties @@ -0,0 +1,63 @@ +# 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. + +report.title=Plugin Updates Aggregate Report +report.description=Provides aggregated details of the plugins used by this project which have newer versions available. +report.overview.title=Overview +report.overview.text=This report summarizes newer versions that may be available for your project's various \ + plugins. +report.overview.pluginManagement=Plugin Management +report.overview.noPluginManagement=This project does not declare any plugins in a build/pluginManagement section. +report.overview.plugin=Plugins +report.overview.noPlugin=This project does not declare any plugins in a build/plugins section. +report.overview.numUpToDate=# of plugins using the latest version available +report.overview.numNewerMajorAvailable=# of plugins where the next version available is a major version update +report.overview.numNewerMinorAvailable=# of plugins where the next version available is a minor version update +report.overview.numNewerIncrementalAvailable=# of plugins where the next version available is an incremental \ + version update +report.overview.numNewerVersionAvailable=# of plugins where the next version available is smaller than an \ + incremental version update +report.overview.numNewerDependenciesAvailable=# of plugins where a dependencies section containes a dependency \ + with an updated version +report.detail.title=Plugin Updates +report.detail.text= +report.status=Status +report.groupId=Group Id +report.artifactId=Artifact Id +report.currentVersion=Current Version +report.scope=Scope +report.classifier=Classifier +report.type=Type +report.latestSubIncremental=Latest Subincremental +report.latestIncremental=Latest Incremental +report.latestMinor=Latest Minor +report.latestMajor=Latest Major +report.dependencyStatus=Dependency status +report.updateVersions=Newer versions +report.noUpdatesAvailable=No newer versions available. +report.otherUpdatesAvailable=There is at least one newer version available. +report.incrementalUpdatesAvailable=There is at least one newer incremental version available. \ + Incremental updates are typically passive. +report.minorUpdatesAvailable=There is at least one newer minor version available. \ + Minor updates are sometimes passive. +report.majorUpdatesAvailable=There is at least one newer major version available. \ + Major updates are rarely passive. +report.yes=Y +report.no=N +report.pluginDependencies=Dependencies of {0} +report.pluginDependency=Dependency {0} +report.plugin=Plugin {0} diff --git a/versions-maven-plugin/src/main/resources/property-updates-aggregate-report.properties b/versions-maven-plugin/src/main/resources/property-updates-aggregate-report.properties new file mode 100644 index 000000000..2a81c60c5 --- /dev/null +++ b/versions-maven-plugin/src/main/resources/property-updates-aggregate-report.properties @@ -0,0 +1,61 @@ +# 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. + +report.title=Property Updates Aggregate Report +report.description=Provides aggregated details of properties which control versions of dependencies and/or plugins, \ + and indicates any newer versions which are available. +report.overview.title=Overview +report.overview.text=This report summarizes newer versions that may be available for your project's various \ + properties associated with artifacts. +report.overview.dependency=Properties +report.overview.noDependency=This project does not declare any properties associated with artifact versions. +report.overview.numUpToDate=# of properties using the latest version available +report.overview.numNewerMajorAvailable=# of properties where the next version available is a major version update +report.overview.numNewerMinorAvailable=# of properties where the next version available is a minor version update +report.overview.numNewerIncrementalAvailable=# of properties where the next version available is an incremental \ + version update +report.overview.numNewerVersionAvailable=# of properties where the next version available is smaller than an \ + incremental version update +report.overview.property=Summary of properties associated with artifact versions +report.overview.noProperty=No properties associated with artifacts have been defined. +report.detail.title=Properties associated with artifact versions +report.detail.text= +report.status=Status +report.property=Property +report.currentVersion=Current Version +report.latestSubIncremental=Latest Subincremental +report.latestIncremental=Latest Incremental +report.latestMinor=Latest Minor +report.latestMajor=Latest Major +report.updateVersions=Newer versions +report.noUpdatesAvailable=No newer versions available. +report.otherUpdatesAvailable=There is at least one newer version available. +report.incrementalUpdatesAvailable=There is at least one newer incremental version available. \ + Incremental updates are typically passive. +report.minorUpdatesAvailable=There is at least one newer minor version available. \ + Minor updates are sometimes passive. +report.majorUpdatesAvailable=There is at least one newer major version available. \ + Major updates are rarely passive. +report.yes=Yes +report.no=No +report.versionRange=Allowed version range +report.autoLinkDependencies=Infer associations from project +report.banSnapshots=Only use release versions +report.searchReactor=Include projects from reactor +report.preferReactor=Always use reactor projects (even if older or -SNAPSHOT) +report.associations=Associated artifacts +report.excludedVersion=Outside allowed version range