All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.soebes.itf.maven.plugin.InstallMojo Maven / Gradle / Ivy

The newest version!
package com.soebes.itf.maven.plugin;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.maven.RepositoryUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
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.project.MavenProject;
import org.apache.maven.project.artifact.ProjectArtifact;
import org.eclipse.aether.DefaultRepositoryCache;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.ArtifactTypeRegistry;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyFilter;
import org.eclipse.aether.installation.InstallRequest;
import org.eclipse.aether.installation.InstallationException;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
import org.eclipse.aether.util.artifact.SubArtifact;
import org.eclipse.aether.util.filter.DependencyFilterUtils;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * itf-maven-plugin.
 *
 * @author Karl Heinz Marbaise
 * @implNote Several parts are taken from the maven-invoker-plugin.
 */
@Mojo(name = "install", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST,
    requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true)
public class InstallMojo extends AbstractMojo {
  @Parameter(defaultValue = "${session}", required = true, readonly = true)
  private MavenSession session;

  @Parameter(defaultValue = "${project}", required = true, readonly = true)
  private MavenProject project;

  /**
   * This defines the location where the installed artifacts are installed for
   * consumption during the integration tests.
   */
  @Parameter(defaultValue = "${project.build.directory}/itf-repo", required = true)
  private File itfRepository;

  @Component
  private RepositorySystem repositorySystem;

  /**
   * The set of Maven projects in the reactor build.
   */
  @Parameter(defaultValue = "${reactorProjects}", readonly = true)
  private Collection reactorProjects;

  @Parameter(defaultValue = "runtime")
  private String scope;

  public void execute() throws MojoExecutionException, MojoFailureException {
    createTestRepository();

    Map resolvedArtifacts = new LinkedHashMap<>();

    try {

      resolveProjectArtifacts(resolvedArtifacts);
      resolveProjectPoms(project, resolvedArtifacts);
      resolveProjectDependencies(resolvedArtifacts);
      // resolveExtraArtifacts(resolvedArtifacts);
      installArtifacts(resolvedArtifacts);

    } catch (DependencyResolutionException
             | InstallationException
             | ArtifactResolutionException e) {
      throw new MojoExecutionException(e.getMessage(), e);
    }

  }


  private void createTestRepository()
      throws MojoExecutionException {

    if (!itfRepository.exists() && !itfRepository.mkdirs()) {
      throw new MojoExecutionException("Failed to create directory: " + itfRepository);
    }
  }

  private void resolveProjectArtifacts(Map resolvedArtifacts) {

    // pom packaging doesn't have a main artifact
    if (project.getArtifact() != null && project.getArtifact().getFile() != null) {
      Artifact artifact = RepositoryUtils.toArtifact(project.getArtifact());
      resolvedArtifacts.put(ArtifactIdUtils.toId(artifact), artifact);
    }

    project.getAttachedArtifacts().stream()
        .map(RepositoryUtils::toArtifact)
        .forEach(a -> resolvedArtifacts.put(ArtifactIdUtils.toId(a), a));
  }

  private void resolveProjectPoms(MavenProject project, Map resolvedArtifacts)
      throws ArtifactResolutionException {

    if (project == null) {
      return;
    }

    Artifact projectPom = RepositoryUtils.toArtifact(new ProjectArtifact(project));
    if (projectPom.getFile() != null) {
      resolvedArtifacts.put(projectPom.toString(), projectPom);
    } else {
      Artifact artifact = resolveArtifact(projectPom, project.getRemoteProjectRepositories());
      resolvedArtifacts.put(ArtifactIdUtils.toId(artifact), artifact);
    }
    resolveProjectPoms(project.getParent(), resolvedArtifacts);
  }

  private void resolveProjectDependencies(Map resolvedArtifacts)
      throws ArtifactResolutionException, MojoExecutionException, DependencyResolutionException {

    DependencyFilter classpathFilter = DependencyFilterUtils.classpathFilter(scope);

    ArtifactTypeRegistry artifactTypeRegistry =
        session.getRepositorySession().getArtifactTypeRegistry();

    List managedDependencies = Optional.ofNullable(project.getDependencyManagement())
        .map(DependencyManagement::getDependencies)
        .orElseGet(Collections::emptyList)
        .stream()
        .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry))
        .collect(Collectors.toList());

    List dependencies = project.getDependencies().stream()
        .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry))
        .collect(Collectors.toList());

    CollectRequest collectRequest = new CollectRequest();
    collectRequest.setRootArtifact(RepositoryUtils.toArtifact(project.getArtifact()));
    collectRequest.setDependencies(dependencies);
    collectRequest.setManagedDependencies(managedDependencies);

    collectRequest.setRepositories(project.getRemoteProjectRepositories());

    DependencyRequest request = new DependencyRequest(collectRequest, classpathFilter);

    DependencyResult dependencyResult =
        repositorySystem.resolveDependencies(session.getRepositorySession(), request);

    List artifacts = dependencyResult.getArtifactResults().stream()
        .map(ArtifactResult::getArtifact)
        .collect(Collectors.toList());

    artifacts.forEach(a -> resolvedArtifacts.put(ArtifactIdUtils.toId(a), a));
    resolvePomsForArtifacts(artifacts, resolvedArtifacts, collectRequest.getRepositories());
  }

  private void resolvePomsForArtifacts(
      List artifacts,
      Map resolvedArtifacts,
      List remoteRepositories)
      throws ArtifactResolutionException, MojoExecutionException {

    for (Artifact a : artifacts) {
      Artifact artifactResult = resolveArtifact(new SubArtifact(a, "", "pom"), remoteRepositories);
      resolvePomWithParents(artifactResult, resolvedArtifacts, remoteRepositories);
    }
  }

  private void resolvePomWithParents(
      Artifact artifact, Map resolvedArtifacts, List remoteRepositories)
      throws MojoExecutionException, ArtifactResolutionException {

    if (resolvedArtifacts.containsKey(ArtifactIdUtils.toId(artifact))) {
      return;
    }

    Model model = PomUtils.loadPom(artifact.getFile());
    Parent parent = model.getParent();
    if (parent != null) {
      DefaultArtifact pom =
          new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), "", "pom", parent.getVersion());
      Artifact resolvedPom = resolveArtifact(pom, remoteRepositories);
      resolvePomWithParents(resolvedPom, resolvedArtifacts, remoteRepositories);
    }

    resolvedArtifacts.put(ArtifactIdUtils.toId(artifact), artifact);
  }

  private Artifact resolveArtifact(Artifact artifact, List remoteRepositories)
      throws ArtifactResolutionException {

    ArtifactRequest request = new ArtifactRequest();
    request.setArtifact(artifact);
    request.setRepositories(remoteRepositories);
    ArtifactResult artifactResult = repositorySystem.resolveArtifact(session.getRepositorySession(), request);
    return artifactResult.getArtifact();
  }

  private void installArtifacts(Map resolvedArtifacts) throws InstallationException {

    RepositorySystemSession systemSessionForLocalRepo = createSystemSessionForLocalRepo();

    // we can have on dependency two artifacts with the same groupId:artifactId
    // with different version, in such case when we install both in one request
    // metadata will contain only one version

    Map> collect = resolvedArtifacts.values().stream()
        .filter(a -> !hasTheSamePathAsTarget(a, systemSessionForLocalRepo))
        .collect(Collectors.groupingBy(
            a -> String.format("%s:%s:%s", a.getGroupId(), a.getArtifactId(), a.getVersion()),
            LinkedHashMap::new,
            Collectors.toList()));

    for (List artifacts : collect.values()) {
      InstallRequest request = new InstallRequest();
      request.setArtifacts(artifacts);
      repositorySystem.install(systemSessionForLocalRepo, request);
    }
  }


  private boolean hasTheSamePathAsTarget(Artifact artifact, RepositorySystemSession systemSession) {
    try {
      LocalRepositoryManager lrm = systemSession.getLocalRepositoryManager();
      File targetBasedir = lrm.getRepository().getBasedir();
      if (targetBasedir == null) {
        return false;
      }
      File targetFile = new File(targetBasedir, lrm.getPathForLocalArtifact(artifact)).getCanonicalFile();
      File sourceFile = artifact.getFile().getCanonicalFile();
      if (Objects.equals(targetFile, sourceFile)) {
        getLog().debug("Skip install the same target " + sourceFile);
        return true;
      }
      return false;
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }


  /**
   * Create a new {@link  RepositorySystemSession} connected with local repo.
   */
  private RepositorySystemSession createSystemSessionForLocalRepo() {
    RepositorySystemSession repositorySystemSession = session.getRepositorySession();
    if (itfRepository != null) {
      // "clone" repository session and replace localRepository
      DefaultRepositorySystemSession newSession =
          new DefaultRepositorySystemSession(session.getRepositorySession());
      // Clear cache, since we're using a new local repository
      newSession.setCache(new DefaultRepositoryCache());
      // keep same repositoryType
      String contentType = newSession.getLocalRepository().getContentType();
      if ("enhanced".equals(contentType)) {
        contentType = "default";
      }
      LocalRepositoryManager localRepositoryManager = repositorySystem.newLocalRepositoryManager(
          newSession, new LocalRepository(itfRepository, contentType));

      newSession.setLocalRepositoryManager(localRepositoryManager);
      repositorySystemSession = newSession;
      getLog().debug("itfRepositoryPath: "
                     + localRepositoryManager.getRepository().getBasedir());
    }

    return repositorySystemSession;
  }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy