diff --git a/src/it/ISSUE-324/README.txt b/src/it/ISSUE-324/README.txt new file mode 100644 index 000000000..911bfbb5d --- /dev/null +++ b/src/it/ISSUE-324/README.txt @@ -0,0 +1,5 @@ +Demonstrates that the aggregateAddThirdParty plugin only resolves the actually used version of a dependency, and not all versions that are present in transitive dependencies. + +The project contains a child2 that depends on hbase-annotations:2.1.3. It also contains child1 which depends on hive-hcatalog-core:2.3.4. The Hive dependency also depends on hbase-annotations, but in a much older version, and through a longer dependency chain. The old hbase-annotations artifact depends on jdk.tools, which is not present in Java 9+. + +The plugin execution will fail if the plugin attempts to resolve jdk.tools on Java 9+. This test is therefore only meaningful on Java 9+, and will pass spuriously on earlier versions. \ No newline at end of file diff --git a/src/it/ISSUE-324/child1/pom.xml b/src/it/ISSUE-324/child1/pom.xml new file mode 100644 index 000000000..e028e6051 --- /dev/null +++ b/src/it/ISSUE-324/child1/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + org.codehaus.mojo.license.test + test-ISSUE-324 + @pom.version@ + + test-ISSUE-324-child1 + jar + + + + + org.apache.hive.hcatalog + hive-hcatalog-core + 2.3.4 + + + + org.codehaus.mojo.license.test + test-ISSUE-324-child2 + @pom.version@ + + + \ No newline at end of file diff --git a/src/it/ISSUE-324/child2/pom.xml b/src/it/ISSUE-324/child2/pom.xml new file mode 100644 index 000000000..bd84f41fa --- /dev/null +++ b/src/it/ISSUE-324/child2/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + org.codehaus.mojo.license.test + test-ISSUE-324 + @pom.version@ + + test-ISSUE-324-child2 + jar + + + + org.apache.hbase + hbase-annotations + 2.1.3 + + + \ No newline at end of file diff --git a/src/it/ISSUE-324/invoker.properties b/src/it/ISSUE-324/invoker.properties new file mode 100644 index 000000000..9d97f4f12 --- /dev/null +++ b/src/it/ISSUE-324/invoker.properties @@ -0,0 +1,23 @@ +### +# #%L +# License Maven Plugin +# %% +# Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# . +# #L% +### +invoker.goals=clean package -e +invoker.failureBehavior=fail-fast \ No newline at end of file diff --git a/src/it/ISSUE-324/pom.xml b/src/it/ISSUE-324/pom.xml new file mode 100644 index 000000000..aeeb2dec5 --- /dev/null +++ b/src/it/ISSUE-324/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + org.codehaus.mojo.license.test + test-ISSUE-324 + @pom.version@ + License Test :: ISSUE-324 + pom + + + + The GNU Lesser General Public License, Version 3.0 + http://www.gnu.org/licenses/lgpl-3.0.txt + repo + + + + + UTF-8 + true + + + + child1 + child2 + + + + + + org.codehaus.mojo + license-maven-plugin + false + @pom.version@ + + system,test + + + + generate-and-check-licenses + + aggregate-add-third-party + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java index 6c95c5889..85fa6dfae 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java @@ -565,8 +565,8 @@ Collection createThirdPartyDetails( MavenProject project, boo ResolvedProjectDependencies loadedDependencies; if ( loadArtifacts ) { - loadedDependencies = dependenciesTool.loadProjectArtifacts( localRepository, - project.getRemoteArtifactRepositories(), project, null ); + loadedDependencies = + new ResolvedProjectDependencies( project.getArtifacts(), project.getDependencyArtifacts() ); } else { diff --git a/src/main/java/org/codehaus/mojo/license/AddThirdPartyMojo.java b/src/main/java/org/codehaus/mojo/license/AddThirdPartyMojo.java index 446d7a641..5a91acc04 100644 --- a/src/main/java/org/codehaus/mojo/license/AddThirdPartyMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AddThirdPartyMojo.java @@ -238,8 +238,8 @@ protected ResolvedProjectDependencies resolveDependencyArtifacts() throws Depend } if ( isAggregatorBuild ) { - dependencyArtifacts = dependenciesTool.loadProjectArtifacts( localRepository, remoteRepositories, - project, reactorProjectDependencies ); + dependencyArtifacts = + new ResolvedProjectDependencies( project.getArtifacts(), project.getDependencyArtifacts() ); } else { diff --git a/src/main/java/org/codehaus/mojo/license/api/DependenciesTool.java b/src/main/java/org/codehaus/mojo/license/api/DependenciesTool.java index 7beaecb30..575053b4f 100644 --- a/src/main/java/org/codehaus/mojo/license/api/DependenciesTool.java +++ b/src/main/java/org/codehaus/mojo/license/api/DependenciesTool.java @@ -22,38 +22,23 @@ * #L% */ -import org.apache.commons.lang3.tuple.Pair; import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.factory.ArtifactFactory; -import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.resolver.ArtifactNotFoundException; -import org.apache.maven.artifact.resolver.ArtifactResolutionException; -import org.apache.maven.artifact.resolver.ArtifactResolutionResult; -import org.apache.maven.artifact.resolver.ArtifactResolver; -import org.apache.maven.model.Dependency; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; import org.apache.maven.project.ProjectBuildingException; -import org.apache.maven.project.artifact.InvalidDependencyVersionException; -import org.apache.maven.project.artifact.MavenMetadataSource; import org.codehaus.mojo.license.utils.MojoHelper; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.logging.Logger; -import java.util.ArrayDeque; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Queue; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; -import java.util.Map.Entry; /** * A tool to deal with dependencies of a project. @@ -78,15 +63,6 @@ public class DependenciesTool @Requirement private MavenProjectBuilder mavenProjectBuilder; - @Requirement - private ArtifactFactory artifactFactory; - - @Requirement - private ArtifactResolver artifactResolver; - - @Requirement - private ArtifactMetadataSource artifactMetadataSource; - // CHECKSTYLE_OFF: MethodLength /** * For a given {@code project}, obtain the universe of its dependencies after applying transitivity and @@ -263,191 +239,4 @@ public SortedMap loadProjectDependencies( ResolvedProjectD return result; } // CHECKSTYLE_ON: MethodLength - - /** - * Load project artifacts. - * - * @param localRepository local repository used to resolv dependencies - * @param remoteRepositories remote repositories used to resolv dependencies - * @param project the project to scan - * @param reactorProjectDependencies reactor projects. Optional, only relevant if there is more than one) - * @return the loaded project dependency artifacts - * @throws DependenciesToolException if could not load project dependencies - */ - @SuppressWarnings( "unchecked" ) - public ResolvedProjectDependencies loadProjectArtifacts( ArtifactRepository localRepository, - List remoteRepositories, MavenProject project, List reactorProjects ) - throws DependenciesToolException - - { - Map idToReactorProject = new HashMap<>(); - if ( reactorProjects != null ) - { - for ( MavenProject reactorProject : reactorProjects ) - { - idToReactorProject.put( String.format( "%s:%s", reactorProject.getGroupId(), - reactorProject.getArtifactId() ), reactorProject ); - } - } - - /* - * Find the list of dependencies to resolve transitively. Some projects may be in the reactor. - * Reactor projects can't be resolved by the artifact resolver yet. - * In order to still get the complete dependency tree for the project, we will add the transitive - * dependencies of the reactor project to the list of dependencies to resolve. - * Since the transitive dependencies could - * also be reactor projects, we need to repeat this check for each of those. - * Note that since the dependency reactor - * project may specify its own list of repositories, - * we need to keep track of which project the transitive dependency is declared in. - */ - List directDependencies = new ArrayList<>( project.getDependencies() ); - Map> reactorProjectToTransitiveDependencies = new HashMap<>(); - Queue> dependenciesToCheck = new ArrayDeque<>(); - for ( Dependency dependency : directDependencies ) - { - dependenciesToCheck.add( Pair.of( project, dependency ) ); - } - if ( reactorProjects != null ) - { - while ( !dependenciesToCheck.isEmpty() ) - { - Pair pair = dependenciesToCheck.remove(); - Dependency dependency = pair.getRight(); - String id = String.format( "%s:%s", dependency.getGroupId(), dependency.getArtifactId() ); - MavenProject dependencyReactorProject = idToReactorProject.get( id ); - if ( dependencyReactorProject != null ) - { - /* - * Since the project is in the reactor, the artifact resolver may not be able to resolve - * the artifact plus transitive dependencies yet. In order to still get the - * complete dependency tree for the project, we will add the transitive - * dependencies of the reactor project to the list of dependencies to resolve. - * Since the transitive dependencies could - * also be reactor projects, we need to repeat this check for each of those. - * Note that since the dependency reactor - * project may specify its own list of repositories, - * we need to keep track of which project the transitive dependency is - * declared in. - */ - for ( Dependency transitiveDependency - : ( List ) dependencyReactorProject.getDependencies() ) - { - dependenciesToCheck.add( Pair.of( dependencyReactorProject, transitiveDependency ) ); - } - } - if ( !directDependencies.contains( dependency ) ) - { - List transitiveForSameProject = - reactorProjectToTransitiveDependencies.get( pair.getLeft() ); - if ( transitiveForSameProject == null ) - { - transitiveForSameProject = new ArrayList<>(); - reactorProjectToTransitiveDependencies.put( pair.getLeft(), transitiveForSameProject ); - } - transitiveForSameProject.add( dependency ); - } - } - } - - //Create artifacts for all dependencies, - //keep the transitive dependencies grouped by project they are declared in - Set directDependencyArtifacts = createDependencyArtifacts( project, directDependencies ); - Map> reactorProjectToDependencyArtifacts = new HashMap<>(); - for ( Entry> entry : reactorProjectToTransitiveDependencies.entrySet() ) - { - reactorProjectToDependencyArtifacts.put( entry.getKey(), - createDependencyArtifacts( entry.getKey(), entry.getValue() ) ); - } - - //Resolve artifacts. Transitive dependencies are resolved with the settings of the POM they are declared in. - //Skip reactor projects, since they can't necessarily be resolved yet. - //The transitive handling above ensures we still get a complete list of dependencies. - Set reactorArtifacts = new HashSet<>(); - Set directArtifactsToResolve = new HashSet<>(); - if ( reactorProjects == null ) - { - directArtifactsToResolve.addAll( directDependencyArtifacts ); - } - else - { - partitionByIsReactorProject( directDependencyArtifacts, reactorArtifacts, - directArtifactsToResolve, idToReactorProject.keySet() ); - for ( Entry> entry : reactorProjectToDependencyArtifacts.entrySet() ) - { - Set nonReactorArtifacts = new HashSet<>(); - partitionByIsReactorProject( entry.getValue(), reactorArtifacts, - nonReactorArtifacts, idToReactorProject.keySet() ); - entry.setValue( nonReactorArtifacts ); - } - } - Set allDependencies = new HashSet<>( reactorArtifacts ); - allDependencies.addAll( resolve( directArtifactsToResolve, project.getArtifact(), localRepository, - remoteRepositories ).getArtifacts() ); - for ( Entry> entry : reactorProjectToDependencyArtifacts.entrySet() ) - { - MavenProject reactorProject = entry.getKey(); - Set toResolve = entry.getValue(); - Artifact reactorProjectArtifact = reactorProject.getArtifact(); - List reactorRemoteRepositories = reactorProject.getRemoteArtifactRepositories(); - allDependencies.addAll( - resolve( toResolve, reactorProjectArtifact, localRepository, - reactorRemoteRepositories ).getArtifacts() ); - } - - return new ResolvedProjectDependencies( allDependencies, directDependencyArtifacts ); - } - - @SuppressWarnings( "unchecked" ) - private Set createDependencyArtifacts( MavenProject project, List dependencies ) - throws DependenciesToolException - { - try - { - return MavenMetadataSource.createArtifacts( artifactFactory, dependencies, null, null, project ); - } - catch ( InvalidDependencyVersionException e ) - { - throw new DependenciesToolException( e ); - } - } - - private void partitionByIsReactorProject( Set artifacts, Set reactorArtifacts, - Set nonReactorArtifacts, Set reactorProjectIds ) - { - for ( Artifact dependencyArtifact : artifacts ) - { - String artifactKey = String.format( "%s:%s", dependencyArtifact.getGroupId(), - dependencyArtifact.getArtifactId() ); - if ( reactorProjectIds.contains( artifactKey ) ) - { - reactorArtifacts.add( dependencyArtifact ); - } - else - { - nonReactorArtifacts.add( dependencyArtifact ); - } - } - } - - private ArtifactResolutionResult resolve( Set artifacts, Artifact projectArtifact, - ArtifactRepository localRepository, List remoteRepositories ) - throws DependenciesToolException - { - try - { - return artifactResolver.resolveTransitively( artifacts, projectArtifact, remoteRepositories, - localRepository, artifactMetadataSource ); - } - catch ( ArtifactResolutionException e ) - { - throw new DependenciesToolException( e ); - } - catch ( ArtifactNotFoundException e ) - { - throw new DependenciesToolException( e ); - } - } - - }