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

com.edugility.maven.Artifacts Maven / Gradle / Ivy

/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
 *
 * Copyright (c) 2013 Edugility LLC.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * The original copy of this license is available at
 * http://www.opensource.org/license/mit-license.html.
 */
package com.edugility.maven;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.maven.artifact.Artifact;

import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.resolver.DefaultResolutionErrorHandler;

import org.apache.maven.artifact.resolver.filter.ArtifactFilter;

import org.apache.maven.artifact.repository.ArtifactRepository;

import org.apache.maven.project.MavenProject;

import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
import org.apache.maven.shared.dependency.graph.DependencyNode;

import org.apache.maven.shared.dependency.graph.traversal.CollectingDependencyNodeVisitor;

/**
 * A utility class for working with {@link Artifact}s.
 *
 * @author Laird Nelson
 *
 * @see Artifact
 *
 * @see #getArtifactsInTopologicalOrder(MavenProject,
 * DependencyGraphBuilder, ArtifactFilter, ArtifactResolver,
 * ArtifactRepository)
 */
public class Artifacts {


  /*
   * Static fields.
   */

  
  /**
   * A {@link ScopeComparator} used to sort the {@link List} returned
   * by the {@link #getArtifactsInTopologicalOrder(MavenProject,
   * DependencyGraphBuilder, ArtifactFilter, ArtifactResolver,
   * ArtifactRepository)} method.
   *
   * 

This field is never {@code null}.

*/ private static final ScopeComparator scopeComparator = new ScopeComparator(); /* * Constructors. */ /** * Creates a new {@link Artifact}s instance. */ public Artifacts() { super(); } /* * Instance methods. */ /** * Returns a {@link Logger} suitable for this {@link Artifacts} * class. * *

This method never returns {@code null}.

* *

The default implementation returns the result of invoking * {@link Logger#getLogger(String) * Logger.getLogger(this.getClass().getName())}.

* * @return a non-{@code null} {@link Logger} */ protected Logger getLogger() { return Logger.getLogger(this.getClass().getName()); } /** * Returns an unmodifiable, non-{@code null} {@link Collection} of * {@link Artifact}s, each element of which is a non-{@code null} * {@link Artifact} that represents either the supplied {@link * MavenProject} itself or a {@linkplain MavenProject#getArtifacts() * dependency of it}. * *

The returned {@link Artifact} {@link Collection} will be * sorted in topological order, from an {@link Artifact} with no * dependencies as the first element, to the {@link Artifact} * representing the {@link MavenProject} itself as the last.

* *

All {@link Artifact}s that are not {@linkplain * Object#equals(Object) equal to} the return value of {@link * MavenProject#getArtifact() project.getArtifact()} will be * {@linkplain ArtifactResolver#resolve(ArtifactResolutionRequest) * resolved} if they are not already {@linkplain * Artifact#isResolved() resolved}. No guarantee of {@linkplain * Artifact#isResolved() resolution status} is made of the * {@linkplain MavenProject#getArtifact() project * Artifact}, which in normal—possibly * all?—cases will be unresolved.

* * @param project the {@link MavenProject} for which resolved {@link * Artifact}s should be returned; must not be {@code null} * * @param dependencyGraphBuilder the {@link DependencyGraphBuilder} * instance that will calculate the dependency graph whose postorder * traversal will yield the {@link Artifact}s to be resolved; must * not be {@code null} * * @param filter an {@link ArtifactFilter} used during {@linkplain * DependencyGraphBuilder#buildDependencyGraph(MavenProject, * ArtifactFilter) dependency graph assembly}; may be {@code null} * * @param resolver an {@link ArtifactResolver} that will use the Maven * 3.0.5 Artifact resolution algorithm to resolve * {@link Artifact}s returned by the {@link * DependencyGraphBuilder#buildDependencyGraph(MavenProject, * ArtifactFilter)} method; must not be {@code null} * * @param localRepository an {@link ArtifactRepository} representing * the local Maven repository in effect; may be {@code null} * * @return a non-{@code null}, {@linkplain * Collections#unmodifiableCollection(Collection) unmodifiable} * {@link Collection} of non-{@code null} {@link Artifact} instances * * @exception IllegalArgumentException if {@code project}, {@code * dependencyGraphBuilder} or {@code resolver} is {@code null} * * @exception ArtifactResolutionException if there were problems * {@linkplain ArtifactResolver#resolve(ArtifactResolutionRequest) * resolving} {@link Artifact} instances * * @exception DependencyGraphBuilderException if there were problems * {@linkplain * DependencyGraphBuilder#buildDependencyGraph(MavenProject, * ArtifactFilter) building the dependency graph} * * @see ArtifactResolver#resolve(ArtifactResolutionRequest) * * @see DependencyGraphBuilder#buildDependencyGraph(MavenProject, * ArtifactFilter) */ public Collection getArtifactsInTopologicalOrder(final MavenProject project, final DependencyGraphBuilder dependencyGraphBuilder, final ArtifactFilter filter, final ArtifactResolver resolver, final ArtifactRepository localRepository) throws DependencyGraphBuilderException, ArtifactResolutionException { final Logger logger = this.getLogger(); if (logger != null && logger.isLoggable(Level.FINER)) { logger.entering(this.getClass().getName(), "getArtifactsInTopologicalOrder", new Object[] { project, dependencyGraphBuilder, filter, resolver, localRepository }); } if (project == null) { throw new IllegalArgumentException("project", new NullPointerException("project")); } if (dependencyGraphBuilder == null) { throw new IllegalArgumentException("dependencyGraphBuilder", new NullPointerException("dependencyGraphBuilder")); } if (resolver == null) { throw new IllegalArgumentException("resolver", new NullPointerException("resolver")); } List returnValue = null; final DependencyNode projectNode = dependencyGraphBuilder.buildDependencyGraph(project, filter); assert projectNode != null; final CollectingDependencyNodeVisitor visitor = new CollectingDependencyNodeVisitor(); projectNode.accept(visitor); final Collection nodes = visitor.getNodes(); if (nodes == null || nodes.isEmpty()) { if (logger != null && logger.isLoggable(Level.FINE)) { logger.logp(Level.FINE, this.getClass().getName(), "getArtifactsInTopologicalOrder", "No dependency nodes encountered"); } } else { final Artifact projectArtifact = project.getArtifact(); returnValue = new ArrayList(); for (final DependencyNode node : nodes) { if (node != null) { Artifact artifact = node.getArtifact(); if (artifact != null) { if (!artifact.isResolved()) { if (logger != null && logger.isLoggable(Level.FINE)) { logger.logp(Level.FINE, this.getClass().getName(), "getArtifactsInTopologicalOrder", "Artifact {0} is unresolved", artifact); } if (artifact.equals(projectArtifact)) { // First see if the artifact is the project artifact. // If so, then it by definition won't be able to be // resolved, because it's being built. if (logger != null && logger.isLoggable(Level.FINE)) { logger.logp(Level.FINE, this.getClass().getName(), "getArtifactsInTopologicalOrder", "Artifact {0} resolved to project artifact: {1}", new Object[] { artifact, projectArtifact }); } artifact = projectArtifact; } else { // See if the project's associated artifact map // contains a resolved version of this artifact. The // artifact map contains all transitive dependency // artifacts of the project. Each artifact in the map // is guaranteed to be resolved. @SuppressWarnings("unchecked") final Map artifactMap = project.getArtifactMap(); if (artifactMap != null && !artifactMap.isEmpty()) { final Artifact mapArtifact = artifactMap.get(new StringBuilder(artifact.getGroupId()).append(":").append(artifact.getArtifactId()).toString()); if (mapArtifact != null) { if (logger != null && logger.isLoggable(Level.FINE)) { logger.logp(Level.FINE, this.getClass().getName(), "getArtifactsInTopologicalOrder", "Artifact {0} resolved from project artifact map: {1}", new Object[] { artifact, mapArtifact }); } artifact = mapArtifact; } } if (!artifact.isResolved()) { // Finally, perform manual artifact resolution. final ArtifactResolutionRequest request = new ArtifactResolutionRequest(); request.setArtifact(artifact); request.setLocalRepository(localRepository); @SuppressWarnings("unchecked") final List remoteRepositories = project.getRemoteArtifactRepositories(); request.setRemoteRepositories(remoteRepositories); if (logger != null && logger.isLoggable(Level.FINE)) { logger.logp(Level.FINE, this.getClass().getName(), "getArtifactsInTopologicalOrder", "Resolving artifact {0} using ArtifactResolutionRequest {1}", new Object[] { artifact, request }); } final ArtifactResolutionResult result = resolver.resolve(request); if (result == null || !result.isSuccess()) { this.handleArtifactResolutionError(request, result); } else { @SuppressWarnings("unchecked") final Collection resolvedArtifacts = (Set)result.getArtifacts(); if (resolvedArtifacts == null || resolvedArtifacts.isEmpty()) { if (logger != null && logger.isLoggable(Level.WARNING)) { logger.logp(Level.WARNING, this.getClass().getName(), "getArtifactsInTopologicalOrder", "Artifact resolution failed silently for artifact {0}", artifact); } } else { final Artifact resolvedArtifact = resolvedArtifacts.iterator().next(); if (resolvedArtifact != null) { assert resolvedArtifact.isResolved(); artifact = resolvedArtifact; } else if (logger != null && logger.isLoggable(Level.WARNING)) { logger.logp(Level.WARNING, this.getClass().getName(), "getArtifactsInTopologicalOrder", "Artifact resolution failed silently for artifact {0}", artifact); } } } } } } if (artifact != null) { returnValue.add(artifact); } } } } if (!returnValue.isEmpty()) { Collections.reverse(returnValue); Collections.sort(returnValue, scopeComparator); } } if (returnValue == null) { returnValue = Collections.emptyList(); } else { returnValue = Collections.unmodifiableList(returnValue); } if (logger != null && logger.isLoggable(Level.FINER)) { logger.exiting(this.getClass().getName(), "getArtifactsInTopologicalOrder", returnValue); } return returnValue; } /** * Handles an error that is represented by the supplied {@link * ArtifactResolutionResult} that was issued in response to the * supplied {@link ArtifactResolutionRequest}. * *

This implementation performs the following operations:

* *
new {@link
   * DefaultResolutionErrorHandler#DefaultResolutionErrorHandler()
   * DefaultResolutionErrorHandler()}.{@link
   * DefaultResolutionErrorHandler#throwErrors(ArtifactResolutionRequest,
   * ArtifactResolutionResult) throwErrors(request,
   * result)};
* * @param request the {@link ArtifactResolutionRequest} that caused * the error; must not be {@code null} * * @param result the {@link ArtifactResolutionResult} that resulted; * must not be {@code null} * * @exception ArtifactResolutionException if this method is not * overridden to do something else * * @see DefaultResolutionErrorHandler * * @see * DefaultResolutionErrorHandler#throwErrors(ArtifactResolutionRequest, * ArtifactResolutionResult) */ protected void handleArtifactResolutionError(final ArtifactResolutionRequest request, final ArtifactResolutionResult result) throws ArtifactResolutionException { new DefaultResolutionErrorHandler().throwErrors(request, result); } /* * Inner and nested classes. */ /** * A {@link Comparator} of {@link Artifact}s that sorts {@code * test}-scoped {@link Artifact}s to the "right". * *

Note: this {@linkplain Comparator comparator} imposes * orderings that are {@linkplain Comparator#compare(Object, Object) * inconsistent with equals}.

* *

Instances of this class are safe for use by concurrent {@link * Thread}s.

* * @author Laird Nelson * * @see Comparator * * @see Artifact * * @see Artifact#getScope() */ private static final class ScopeComparator implements Comparator { /** * Creates a new {@link ScopeComparator}. */ private ScopeComparator() { super(); } /** * Compares the two supplied {@link Artifact}s by testing * {@linkplain Artifact#getScope() their affiliated scopes}. * * @param a1 the first {@link Artifact} to test; must not be * {@code null} * * @param a2 the second {@link Artifact} to test; must not be * {@code null} * * @return {@code 1} when the first {@link Artifact} has a * {@linkplain Artifact#getScope() scope} of {@code test} and the * second one doesn't; {@code -1} when the second {@link Artifact} * has a {@linkplain Artifact#getScope() scope} of {@code test} * and the first one doesn't; {@code 0} in all other cases * * @exception NullPointerException if either {@code a1} or {@code * a2} is {@code null} */ @Override public final int compare(final Artifact a1, final Artifact a2) { if (a1 == null) { throw new NullPointerException("a1"); } if (a2 == null) { throw new NullPointerException("a2"); } if ("test".equals(a1.getScope())) { if (!"test".equals(a2.getScope())) { return 1; // test scopes sort to the right/come at the end } } else if ("test".equals(a2.getScope())) { return -1; } return 0; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy