DependencyBuilder.java
- /*
- * 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.
- */
- package org.basepom.inline.mojo;
- import static com.google.common.base.Preconditions.checkNotNull;
- import static com.google.common.collect.ImmutableSet.toImmutableSet;
- import java.util.List;
- import java.util.Objects;
- import com.google.common.base.Throwables;
- import com.google.common.collect.ImmutableList;
- import com.google.common.collect.ImmutableSet;
- import org.apache.maven.RepositoryUtils;
- import org.apache.maven.execution.MavenSession;
- import org.apache.maven.project.DefaultDependencyResolutionRequest;
- import org.apache.maven.project.DefaultProjectBuildingRequest;
- import org.apache.maven.project.DependencyResolutionException;
- import org.apache.maven.project.DependencyResolutionRequest;
- import org.apache.maven.project.DependencyResolutionResult;
- import org.apache.maven.project.MavenProject;
- import org.apache.maven.project.ProjectBuilder;
- import org.apache.maven.project.ProjectBuildingException;
- import org.apache.maven.project.ProjectBuildingRequest;
- import org.apache.maven.project.ProjectBuildingResult;
- import org.apache.maven.project.ProjectDependenciesResolver;
- import org.eclipse.aether.artifact.Artifact;
- import org.eclipse.aether.artifact.DefaultArtifact;
- import org.eclipse.aether.graph.Dependency;
- import org.eclipse.aether.graph.DependencyFilter;
- import org.eclipse.aether.repository.RemoteRepository;
- import org.eclipse.aether.transfer.ArtifactTransferException;
- import org.eclipse.aether.transfer.NoRepositoryLayoutException;
- import org.eclipse.aether.util.artifact.JavaScopes;
- /**
- * Builds a map of dependencies required by a specific project or another dependency.
- */
- final class DependencyBuilder {
- private static final PluginLog LOG = new PluginLog(DependencyBuilder.class);
- private final MavenProject rootProject;
- private final MavenSession mavenSession;
- private final ProjectBuilder projectBuilder;
- private final ProjectDependenciesResolver projectDependenciesResolver;
- private final List<MavenProject> reactorProjects;
- DependencyBuilder(MavenProject rootProject, MavenSession mavenSession, ProjectBuilder projectBuilder,
- ProjectDependenciesResolver projectDependenciesResolver, List<MavenProject> reactorProjects) {
- this.rootProject = rootProject;
- this.mavenSession = mavenSession;
- this.projectBuilder = projectBuilder;
- this.projectDependenciesResolver = projectDependenciesResolver;
- this.reactorProjects = ImmutableList.copyOf(reactorProjects);
- }
- /**
- * Create a map of dependencies for a given dependency node (representing an element on the dependency tree).
- *
- * @param dependency The dependency node to use.
- * @param projectScopeFilter A scope limiting filter to mask out dependencies out of scope.
- * @return A map of dependencies for this given dependency node.
- * @throws DependencyResolutionException Dependency resolution failed.
- * @throws ProjectBuildingException Maven project could not be built.
- */
- ImmutableList<Dependency> mapDependency(final Dependency dependency,
- final DependencyFilter projectScopeFilter)
- throws DependencyResolutionException, ProjectBuildingException {
- checkNotNull(dependency, "dependency is null");
- // build the project
- final ProjectBuildingResult result = projectBuilder.build(convertFromAetherDependency(dependency), false, createProjectBuildingRequest());
- // now resolve the project representing the dependency.
- final MavenProject project = result.getProject();
- return mapProject(project, projectScopeFilter);
- }
- /**
- * Create a map of names to dependencies for a given project.
- *
- * @param project The current maven project.
- * @param scopeFilter A scope limiting filter to mask out dependencies out of scope.
- * @return A map of dependencies for this given dependency node.
- * @throws DependencyResolutionException Dependency resolution failed.
- */
- ImmutableList<Dependency> mapProject(final MavenProject project,
- final DependencyFilter scopeFilter)
- throws DependencyResolutionException {
- checkNotNull(project, "project is null");
- final DependencyResolutionRequest request = new DefaultDependencyResolutionRequest();
- request.setRepositorySession(createProjectBuildingRequest().getRepositorySession());
- request.setMavenProject(project);
- request.setResolutionFilter(scopeFilter);
- DependencyResolutionResult result;
- try {
- result = projectDependenciesResolver.resolve(request);
- } catch (DependencyResolutionException e) {
- result = e.getResult();
- // try to resolve using the reactor projects
- final ImmutableSet<ProjectKey> reactorProjects = this.reactorProjects.stream()
- .map(ProjectKey::fromProject).collect(toImmutableSet());
- // resolve all dependencies that are matched by the reactor.
- final ImmutableSet<Dependency> reactorDependencies = result.getUnresolvedDependencies().stream()
- .filter(d -> reactorProjects.contains(ProjectKey.fromDependency(d)))
- .collect(toImmutableSet());
- result.getUnresolvedDependencies().removeAll(reactorDependencies);
- result.getResolvedDependencies().addAll(reactorDependencies);
- // remove all unresolved system dependencies
- final ImmutableSet<Dependency> systemDependencies = result.getUnresolvedDependencies().stream()
- .filter(d -> JavaScopes.SYSTEM.equals(d.getScope()))
- .collect(toImmutableSet());
- result.getUnresolvedDependencies().removeAll(systemDependencies);
- result.getResolvedDependencies().addAll(systemDependencies);
- // remove all unresolved optional dependencies
- final ImmutableSet<Dependency> optionalDependencies = result.getUnresolvedDependencies().stream()
- .filter(Dependency::isOptional)
- .collect(toImmutableSet());
- result.getUnresolvedDependencies().removeAll(optionalDependencies);
- result.getResolvedDependencies().addAll(optionalDependencies);
- if (!result.getUnresolvedDependencies().isEmpty()) {
- final Throwable t = Throwables.getRootCause(e);
- RemoteRepository repository = null;
- if (t instanceof NoRepositoryLayoutException) {
- repository = ((NoRepositoryLayoutException) t).getRepository();
- } else if (t instanceof ArtifactTransferException) {
- repository = ((ArtifactTransferException) t).getRepository();
- }
- if (repository != null && "legacy".equals(repository.getContentType())) {
- LOG.warn("Could not access a legacy repository for artifacts: %s; Reason: %s", result.getUnresolvedDependencies(), t.getMessage());
- } else {
- throw e;
- }
- }
- }
- return ImmutableList.copyOf(result.getResolvedDependencies());
- }
- static org.apache.maven.artifact.Artifact convertFromAetherDependency(final Dependency dependency) {
- final var mavenArtifact = RepositoryUtils.toArtifact(convertToPomArtifact(dependency.getArtifact()));
- mavenArtifact.setScope(dependency.getScope());
- mavenArtifact.setOptional(dependency.isOptional());
- return mavenArtifact;
- }
- private ProjectBuildingRequest createProjectBuildingRequest() {
- DefaultProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(mavenSession.getProjectBuildingRequest());
- buildingRequest.setRemoteRepositories(rootProject.getRemoteArtifactRepositories());
- return buildingRequest;
- }
- static Artifact convertToPomArtifact(final Artifact artifact) {
- // pom artifact has no classifier. If this is already a pom artifact, don't touch it.
- if (artifact.getClassifier().isEmpty() && "pom".equals(artifact.getExtension())) {
- return artifact;
- }
- // create a POM artifact.
- return new DefaultArtifact(artifact.getGroupId(), artifact.getArtifactId(), "pom", artifact.getVersion());
- }
- private static final class ProjectKey {
- private final String groupId;
- private final String artifactId;
- private final String version;
- public static ProjectKey fromProject(final MavenProject project) {
- checkNotNull(project, "project; is null");
- return new ProjectKey(project.getGroupId(), project.getArtifactId(), project.getVersion());
- }
- public static ProjectKey fromDependency(final Dependency dependency) {
- checkNotNull(dependency, "artifact; is null");
- return new ProjectKey(dependency.getArtifact().getGroupId(),
- dependency.getArtifact().getArtifactId(),
- dependency.getArtifact().getVersion());
- }
- private ProjectKey(final String groupId, final String artifactId, final String version) {
- this.groupId = checkNotNull(groupId, "groupId is null");
- this.artifactId = checkNotNull(artifactId, "artifactId is null");
- this.version = checkNotNull(version, "version is null");
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- ProjectKey that = (ProjectKey) o;
- return groupId.equals(that.groupId) &&
- artifactId.equals(that.artifactId) &&
- version.equals(that.version);
- }
- @Override
- public int hashCode() {
- return Objects.hash(groupId, artifactId, version);
- }
- }
- }