Skip to content

Commit

Permalink
ISSUE-324: Remove unnecessary manual dependency resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
srdo committed Apr 20, 2019
1 parent 19796fa commit 5604b09
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 215 deletions.
26 changes: 26 additions & 0 deletions src/it/ISSUE-324/child1/pom.xml
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.mojo.license.test</groupId>
<artifactId>test-ISSUE-324</artifactId>
<version>@pom.version@</version>
</parent>
<artifactId>test-ISSUE-324-child1</artifactId>
<packaging>jar</packaging>

<dependencies>
<!-- Depends on old hbase-annotations, which depends on jdk.tools -->
<dependency>
<groupId>org.apache.hive.hcatalog</groupId>
<artifactId>hive-hcatalog-core</artifactId>
<version>2.3.4</version>
</dependency>
<!-- This has a newer hbase-annotations without jdk.tools. This path to hbase-annotations is shorter, so has precedence -->
<dependency>
<groupId>org.codehaus.mojo.license.test</groupId>
<artifactId>test-ISSUE-324-child2</artifactId>
<version>@pom.version@</version>
</dependency>
</dependencies>
</project>
19 changes: 19 additions & 0 deletions src/it/ISSUE-324/child2/pom.xml
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.mojo.license.test</groupId>
<artifactId>test-ISSUE-324</artifactId>
<version>@pom.version@</version>
</parent>
<artifactId>test-ISSUE-324-child2</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-annotations</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
</project>
23 changes: 23 additions & 0 deletions 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
# <http://www.gnu.org/licenses/lgpl-3.0.html>.
# #L%
###
invoker.goals=clean package -e
invoker.failureBehavior=fail-fast
50 changes: 50 additions & 0 deletions src/it/ISSUE-324/pom.xml
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.codehaus.mojo.license.test</groupId>
<artifactId>test-ISSUE-324</artifactId>
<version>@pom.version@</version>
<name>License Test :: ISSUE-324</name>
<packaging>pom</packaging>

<licenses>
<license>
<name>The GNU Lesser General Public License, Version 3.0</name>
<url>http://www.gnu.org/licenses/lgpl-3.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<license.verbose>true</license.verbose>
</properties>

<modules>
<module>child1</module>
<module>child2</module>
</modules>

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<inherited>false</inherited>
<version>@pom.version@</version>
<configuration>
<excludedScopes>system,test</excludedScopes>
</configuration>
<executions>
<execution>
<id>generate-and-check-licenses</id>
<goals>
<goal>aggregate-add-third-party</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Expand Up @@ -565,8 +565,8 @@ Collection<ThirdPartyDetails> createThirdPartyDetails( MavenProject project, boo
ResolvedProjectDependencies loadedDependencies;
if ( loadArtifacts )
{
loadedDependencies = dependenciesTool.loadProjectArtifacts( localRepository,
project.getRemoteArtifactRepositories(), project, null );
loadedDependencies =
new ResolvedProjectDependencies( project.getArtifacts(), project.getDependencyArtifacts() );
}
else
{
Expand Down
Expand Up @@ -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
{
Expand Down
211 changes: 0 additions & 211 deletions src/main/java/org/codehaus/mojo/license/api/DependenciesTool.java
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -263,191 +239,4 @@ public SortedMap<String, MavenProject> 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<ArtifactRepository> remoteRepositories, MavenProject project, List<MavenProject> reactorProjects )
throws DependenciesToolException

{
Map<String, MavenProject> 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<Dependency> directDependencies = new ArrayList<>( project.getDependencies() );
Map<MavenProject, List<Dependency>> reactorProjectToTransitiveDependencies = new HashMap<>();
Queue<Pair<MavenProject, Dependency>> dependenciesToCheck = new ArrayDeque<>();
for ( Dependency dependency : directDependencies )
{
dependenciesToCheck.add( Pair.of( project, dependency ) );
}
if ( reactorProjects != null )
{
while ( !dependenciesToCheck.isEmpty() )
{
Pair<MavenProject, Dependency> 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<Dependency> ) dependencyReactorProject.getDependencies() )
{
dependenciesToCheck.add( Pair.of( dependencyReactorProject, transitiveDependency ) );
}
}
if ( !directDependencies.contains( dependency ) )
{
List<Dependency> 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<Artifact> directDependencyArtifacts = createDependencyArtifacts( project, directDependencies );
Map<MavenProject, Set<Artifact>> reactorProjectToDependencyArtifacts = new HashMap<>();
for ( Entry<MavenProject, List<Dependency>> 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<Artifact> reactorArtifacts = new HashSet<>();
Set<Artifact> directArtifactsToResolve = new HashSet<>();
if ( reactorProjects == null )
{
directArtifactsToResolve.addAll( directDependencyArtifacts );
}
else
{
partitionByIsReactorProject( directDependencyArtifacts, reactorArtifacts,
directArtifactsToResolve, idToReactorProject.keySet() );
for ( Entry<MavenProject, Set<Artifact>> entry : reactorProjectToDependencyArtifacts.entrySet() )
{
Set<Artifact> nonReactorArtifacts = new HashSet<>();
partitionByIsReactorProject( entry.getValue(), reactorArtifacts,
nonReactorArtifacts, idToReactorProject.keySet() );
entry.setValue( nonReactorArtifacts );
}
}
Set<Artifact> allDependencies = new HashSet<>( reactorArtifacts );
allDependencies.addAll( resolve( directArtifactsToResolve, project.getArtifact(), localRepository,
remoteRepositories ).getArtifacts() );
for ( Entry<MavenProject, Set<Artifact>> entry : reactorProjectToDependencyArtifacts.entrySet() )
{
MavenProject reactorProject = entry.getKey();
Set<Artifact> toResolve = entry.getValue();
Artifact reactorProjectArtifact = reactorProject.getArtifact();
List<ArtifactRepository> reactorRemoteRepositories = reactorProject.getRemoteArtifactRepositories();
allDependencies.addAll(
resolve( toResolve, reactorProjectArtifact, localRepository,
reactorRemoteRepositories ).getArtifacts() );
}

return new ResolvedProjectDependencies( allDependencies, directDependencyArtifacts );
}

@SuppressWarnings( "unchecked" )
private Set<Artifact> createDependencyArtifacts( MavenProject project, List<Dependency> dependencies )
throws DependenciesToolException
{
try
{
return MavenMetadataSource.createArtifacts( artifactFactory, dependencies, null, null, project );
}
catch ( InvalidDependencyVersionException e )
{
throw new DependenciesToolException( e );
}
}

private void partitionByIsReactorProject( Set<Artifact> artifacts, Set<Artifact> reactorArtifacts,
Set<Artifact> nonReactorArtifacts, Set<String> 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<Artifact> artifacts, Artifact projectArtifact,
ArtifactRepository localRepository, List<ArtifactRepository> 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 );
}
}


}

0 comments on commit 5604b09

Please sign in to comment.