/**
   * Creates a request for the specified plugin prefix and build session. The provided build session
   * will be used to configure repository settings. If the session has a current project, its plugin
   * repositories and model will be used as well.
   *
   * @param prefix The plugin prefix to resolve, must not be {@code null}.
   * @param session The build session from which to derive further settings, must not be {@code
   *     null}.
   */
  public DefaultPluginPrefixRequest(String prefix, MavenSession session) {
    setPrefix(prefix);

    setRepositorySession(session.getRepositorySession());

    MavenProject project = session.getCurrentProject();
    if (project != null) {
      setRepositories(project.getRemotePluginRepositories());
      setPom(project.getModel());
    }

    setPluginGroups(session.getPluginGroups());
  }
  public MojoExecution createMojoExecution(Plugin plugin, String goal, MavenProject project)
      throws Exception {
    if (plugin.getVersion() == null) {
      plugin.setVersion(
          plexusContainer
              .lookup(PluginVersionResolver.class)
              .resolve(new DefaultPluginVersionRequest(plugin, session))
              .getVersion());
    }

    MojoDescriptor mojoDescriptor =
        pluginManager.getMojoDescriptor(
            plugin, goal, project.getRemotePluginRepositories(), session.getRepositorySession());
    List<PluginExecution> executions = plugin.getExecutions();
    MojoExecution mojoExecution =
        new MojoExecution(
            mojoDescriptor,
            executions.isEmpty() ? null : executions.get(executions.size() - 1).getId(),
            MojoExecution.Source.CLI);
    plexusContainer
        .lookup(LifecycleExecutionPlanCalculator.class)
        .setupMojoExecution(session, project, mojoExecution);
    return mojoExecution;
  }
  @Override
  public Collection<MavenArtifact> resolvePlugin(
      @NotNull MavenPlugin plugin,
      @NotNull List<MavenRemoteRepository> repositories,
      int nativeMavenProjectId,
      boolean transitive)
      throws RemoteException, MavenServerProcessCanceledException {
    try {
      Plugin mavenPlugin = new Plugin();
      mavenPlugin.setGroupId(plugin.getGroupId());
      mavenPlugin.setArtifactId(plugin.getArtifactId());
      mavenPlugin.setVersion(plugin.getVersion());
      MavenProject project = RemoteNativeMavenProjectHolder.findProjectById(nativeMavenProjectId);

      MavenExecutionRequest request =
          createRequest(
              null,
              Collections.<String>emptyList(),
              Collections.<String>emptyList(),
              Collections.<String>emptyList());

      DefaultMaven maven = (DefaultMaven) getComponent(Maven.class);
      RepositorySystemSession repositorySystemSession = maven.newRepositorySession(request);

      if (plugin.getVersion() == null) {
        PluginVersionRequest versionRequest =
            new DefaultPluginVersionRequest(
                mavenPlugin, repositorySystemSession, project.getRemotePluginRepositories());
        mavenPlugin.setVersion(
            getComponent(PluginVersionResolver.class).resolve(versionRequest).getVersion());
      }

      PluginDescriptor result =
          getComponent(MavenPluginManager.class)
              .getPluginDescriptor(
                  mavenPlugin, project.getRemotePluginRepositories(), repositorySystemSession);

      Map<MavenArtifactInfo, MavenArtifact> resolvedArtifacts =
          new THashMap<MavenArtifactInfo, MavenArtifact>();

      Artifact pluginArtifact = result.getPluginArtifact();

      MavenArtifactInfo artifactInfo =
          new MavenArtifactInfo(
              pluginArtifact.getGroupId(),
              pluginArtifact.getArtifactId(),
              pluginArtifact.getVersion(),
              pluginArtifact.getType(),
              null);

      resolveIfNecessary(artifactInfo, repositories, resolvedArtifacts);

      if (transitive) {
        // todo try to use parallel downloading
        for (Artifact each : result.getIntroducedDependencyArtifacts()) {
          resolveIfNecessary(
              new MavenArtifactInfo(
                  each.getGroupId(), each.getArtifactId(), each.getVersion(), each.getType(), null),
              repositories,
              resolvedArtifacts);
        }
        for (ComponentDependency each : result.getDependencies()) {
          resolveIfNecessary(
              new MavenArtifactInfo(
                  each.getGroupId(), each.getArtifactId(), each.getVersion(), each.getType(), null),
              repositories,
              resolvedArtifacts);
        }
      }

      return new THashSet<MavenArtifact>(resolvedArtifacts.values());
    } catch (Exception e) {
      Maven3ServerGlobals.getLogger().info(e);
      return Collections.emptyList();
    }
  }
  public Map<String, List<MojoExecution>> calculateLifecycleMappings(
      MavenSession session, MavenProject project, Lifecycle lifecycle, String lifecyclePhase)
      throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
          MojoNotFoundException, InvalidPluginDescriptorException {
    /*
     * Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller
     * is interested in, i.e. all phases up to and including the specified phase.
     */

    Map<String, Map<Integer, List<MojoExecution>>> mappings =
        new LinkedHashMap<String, Map<Integer, List<MojoExecution>>>();

    for (String phase : lifecycle.getPhases()) {
      Map<Integer, List<MojoExecution>> phaseBindings = new TreeMap<Integer, List<MojoExecution>>();

      mappings.put(phase, phaseBindings);

      if (phase.equals(lifecyclePhase)) {
        break;
      }
    }

    /*
     * Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of
     * the project already contains the plugin executions induced by the project's packaging type. Remember, all
     * phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not
     * interested in any of the executions bound to it.
     */

    for (Plugin plugin : project.getBuild().getPlugins()) {
      for (PluginExecution execution : plugin.getExecutions()) {
        // if the phase is specified then I don't have to go fetch the plugin yet and pull it down
        // to examine the phase it is associated to.
        if (execution.getPhase() != null) {
          Map<Integer, List<MojoExecution>> phaseBindings = mappings.get(execution.getPhase());
          if (phaseBindings != null) {
            for (String goal : execution.getGoals()) {
              MojoExecution mojoExecution = new MojoExecution(plugin, goal, execution.getId());
              mojoExecution.setLifecyclePhase(execution.getPhase());
              addMojoExecution(phaseBindings, mojoExecution, execution.getPriority());
            }
          }
        }
        // if not then i need to grab the mojo descriptor and look at the phase that is specified
        else {
          for (String goal : execution.getGoals()) {
            MojoDescriptor mojoDescriptor =
                pluginManager.getMojoDescriptor(
                    plugin,
                    goal,
                    project.getRemotePluginRepositories(),
                    session.getRepositorySession());

            Map<Integer, List<MojoExecution>> phaseBindings =
                mappings.get(mojoDescriptor.getPhase());
            if (phaseBindings != null) {
              MojoExecution mojoExecution = new MojoExecution(mojoDescriptor, execution.getId());
              mojoExecution.setLifecyclePhase(mojoDescriptor.getPhase());
              addMojoExecution(phaseBindings, mojoExecution, execution.getPriority());
            }
          }
        }
      }
    }

    Map<String, List<MojoExecution>> lifecycleMappings =
        new LinkedHashMap<String, List<MojoExecution>>();

    for (Map.Entry<String, Map<Integer, List<MojoExecution>>> entry : mappings.entrySet()) {
      List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();

      for (List<MojoExecution> executions : entry.getValue().values()) {
        mojoExecutions.addAll(executions);
      }

      lifecycleMappings.put(entry.getKey(), mojoExecutions);
    }

    return lifecycleMappings;
  }