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

org.basepom.mojo.dvc.AbstractDependencyVersionsMojo Maven / Gradle / Ivy

Go to download

The dependency-versions-check plugin verifies that all resolved versions of artifacts are at least the versions specified by the project dependencies. The Maven dependency resolution process will substitute versions for the different artifacts in a dependency tree and sometimes chooses incompatible versions which leads to difficult to detect problems. This plugin resolves all dependencies and collects any requested version. It evaluates whether the resolved versions are compatible to the requested versions and reports possible conflicts.

The newest version!
/*
 * 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.mojo.dvc;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import org.basepom.mojo.dvc.dependency.DependencyMap;
import org.basepom.mojo.dvc.dependency.DependencyMapBuilder;
import org.basepom.mojo.dvc.dependency.DependencyTreeResolver;
import org.basepom.mojo.dvc.model.ResolverDefinition;
import org.basepom.mojo.dvc.model.VersionCheckExcludes;
import org.basepom.mojo.dvc.strategy.StrategyProvider;
import org.basepom.mojo.dvc.version.VersionResolutionCollection;

import java.util.Arrays;
import java.util.List;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import org.apache.maven.execution.MavenSession;
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.Parameter;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectDependenciesResolver;
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.resolution.VersionRangeRequest;
import org.eclipse.aether.util.artifact.JavaScopes;
import org.eclipse.aether.util.graph.version.SnapshotVersionFilter;

/**
 * Base code for all the mojos. Contains the dependency resolvers and the common options.
 */
public abstract class AbstractDependencyVersionsMojo
        extends AbstractMojo
        implements Context {

    private static final ImmutableSet VALID_SCOPES = ImmutableSet.of(
            ScopeLimitingFilter.COMPILE_PLUS_RUNTIME,
            JavaScopes.COMPILE,
            JavaScopes.RUNTIME,
            JavaScopes.TEST);

    protected final PluginLog log = new PluginLog(this.getClass());

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

    @Parameter(defaultValue = "${session}", readonly = true)
    public MavenSession mavenSession;

    @Parameter(defaultValue = "${reactorProjects}", readonly = true, required = true)
    public List reactorProjects;

    @Component
    public ProjectBuilder mavenProjectBuilder;

    @Component
    public ProjectDependenciesResolver projectDependenciesResolver;

    @Component
    public RepositorySystem repositorySystem;

    /**
     * The strategy provider. This can be requested by other pieces to add additional strategies.
     */
    @Component
    public StrategyProvider strategyProvider;

    /**
     * List of version checks that will be removed from the version check. This allows potential conflicts to be excluded.
     * 
*
     * <exclusions>
     *   <exclusion>
     *     <dependency>...</dependency>
     *     <expected>...</expected>
     *     <resolved>...</resolved>
     *   </exclusion>
     * </exclusions>
     * 
*

* Each element consists of a dependency pattern [groupId]:[artifactId] that supports wildcards and an expected version (which is the version * is expected by the artifact) and a resolved version (the version that the dependency resolution has chosen). *

*/ @Parameter(alias = "exceptions") public VersionCheckExcludes[] exclusions = new VersionCheckExcludes[0]; /** * Skip the plugin execution. */ @Parameter(defaultValue = "false", property = "dvc.skip") public boolean skip = false; /** * Include POM projects when running on a multi-module project. Dependency resolution on a pom project almost never makes sense as it does not actually * build any artifacts. * * @since 3.0.0 */ @Parameter(defaultValue = "false", property = "dvc.include-pom-projects") public boolean includePomProjects = false; /** * Silence all non-output and non-error messages. * * @since 3.0.0 */ @Parameter(defaultValue = "false", property = "dvc.quiet") public boolean quiet = false; /** * Dependency resolution scope. Defaults to test. Valid choices are compile+runtime, compile, * test and runtime. * * @since 3.0.0 */ @Parameter(defaultValue = "test", property = "scope") public String scope = JavaScopes.TEST; /** * Use deep scan or regular scan. Deep scan looks at all dependencies in the dependency tree, while regular scan only looks one level deep into the direct * dependencies. * * @since 3.0.0 */ @Parameter(defaultValue = "false", property = "dvc.deep-scan") public boolean deepScan = false; /** * List only direct dependencies or all dependencies. * * @since 3.0.0 */ @Parameter(defaultValue = "false", property = "dvc.direct-only") public boolean directOnly = false; /** * List only managed dependencies or all dependencies. * * @since 3.0.0 */ @Parameter(defaultValue = "false", property = "dvc.managed-only") public boolean managedOnly = false; /** * Run dependency resolution in parallel with multiple threads. Should only ever set to false if the plugin shows stability problems when * resolving dependencies. Please file a bug in that case, too. * * @since 3.0.0 */ @Parameter(defaultValue = "true", property = "dvc.fast-resolution") public boolean fastResolution = true; /** * Fail the build if an artifact in system scope can not be resolved. Those are notoriously dependent on the local build environment and some * outright fail (e.g. referencing the tools.jar, which no longer exists in a JDK8+ environment). *
* Setting this flag to true will fail the build if any system scoped artifact can not be resolved. This is almost never desired, * except when building a project with a direct system scoped dependency. * * @since 3.0.0 */ @Parameter(defaultValue = "false", property = "dvc.unresolved-system-artifacts-fail-build") protected boolean unresolvedSystemArtifactsFailBuild = false; /** * Require all optional dependencies to exist and fail the build if any optional dependency can not resolved. This is almost never needed and actually * causes problems for some projects that use large public dependencies from central that in turn pull in non-public dependencies as optional. * * @since 3.2.0 */ @Parameter(defaultValue = "false", property = "dvc.optional-dependencies-must-exist") protected boolean optionalDependenciesMustExist = false; /** * List of resolvers to apply specific strategies to dependencies. * *
     * <resolvers>
     *   <resolver>
     *     <strategy>...<strategy>
     *     <includes>
     *       <include>...<include>
     *     <includes>
     *   <resolver>
     * <resolvers>
     * 
*

* A resolver maps a specific strategy to a list of includes. The include syntax is [group-id]:[artifact-id] where each pattern segment * supports full and partial wildcards (*). *
* The plugin includes some default strategies: apr, default, single-digit and * two-digits-backward-compatible. Additional strategies can be defined and added to the plugin classpath. */ @Parameter public ResolverDefinition[] resolvers = new ResolverDefinition[0]; /** * Sets the default strategy to use to evaluate whether two dependency versions are compatible or not. *

* The default resolution strategy matches the Maven dependency resolution itself; any two dependencies that maven considers compatible will be * accepted. * * @since 3.0.0 */ @Parameter(defaultValue = "default", property = "dvc.default-strategy") public String defaultStrategy = "default"; protected StrategyCache strategyCache; protected RepositorySystemSession snapshotFilteredSession; @Override @SuppressWarnings("PMD.AvoidRethrowingException") public void execute() throws MojoExecutionException, MojoFailureException { try { for (VersionCheckExcludes exclusion : exclusions) { checkState(exclusion.isValid(), "Invalid exclusion specification: '%s'", exclusion); } checkState(!Strings.nullToEmpty(scope).trim().isEmpty() && VALID_SCOPES.contains(scope), "Scope '%s' is invalid", scope); if (skip) { log.report(quiet, "Skipping plugin execution"); return; } if (!includePomProjects && "pom".equals(project.getPackaging())) { log.report(quiet, "Ignoring POM project"); return; } log.debug("Starting %s mojo run!", this.getClass().getSimpleName()); this.strategyCache = new StrategyCache(strategyProvider, resolvers, defaultStrategy); this.snapshotFilteredSession = new DefaultRepositorySystemSession(mavenSession.getRepositorySession()) .setVersionFilter(new SnapshotVersionFilter()); final ScopeLimitingFilter scopeFilter = createScopeFilter(); final DependencyMap rootDependencyMap = new DependencyMapBuilder(this).mapProject(project, scopeFilter); try (DependencyTreeResolver dependencyTreeResolver = new DependencyTreeResolver(this, rootDependencyMap)) { final ImmutableSetMultimap resolutionMap = dependencyTreeResolver.computeResolutionMap(project, scopeFilter); doExecute(resolutionMap, rootDependencyMap); } } catch (MojoExecutionException | MojoFailureException e) { throw e; } catch (Exception e) { throw new MojoExecutionException("While running mojo: ", e); } finally { log.debug("Ended %s mojo run!", this.getClass().getSimpleName()); } } /** * Subclasses need to implement this method. * * @param resolutionMap The prebuilt resolution map from qualified names to version resolution collections. * @param rootDependencyMap The prebuilt dependency map for all the root dependencies. * @throws Exception When an execution error occurs. */ protected abstract void doExecute(ImmutableSetMultimap resolutionMap, DependencyMap rootDependencyMap) throws Exception; /** * Defines the scope used to resolve the project dependencies. The project dependencies will be limited to the dependencies that match this filter. The list * mojo overrides this to limit the scope in which dependencies are listed. By default, include everything. * * @return The {@link ScopeLimitingFilter} instance for the project dependencies. */ protected ScopeLimitingFilter createScopeFilter() { return ScopeLimitingFilter.computeDependencyScope(scope); } @Override public boolean useFastResolution() { return fastResolution; } @Override public boolean useDeepScan() { return deepScan; } @Override public boolean isOptionalDependenciesMustExist() { return optionalDependenciesMustExist; } @Override public StrategyCache getStrategyCache() { return strategyCache; } @Override public ProjectBuilder getProjectBuilder() { return mavenProjectBuilder; } @Override public ProjectDependenciesResolver getProjectDependenciesResolver() { return projectDependenciesResolver; } @Override public MavenProject getRootProject() { return project; } @Override public List getReactorProjects() { return ImmutableList.copyOf(reactorProjects); } @Override public RepositorySystemSession getRepositorySystemSession() { return snapshotFilteredSession; } @Override public RepositorySystem getRepositorySystem() { return repositorySystem; } @Override public ProjectBuildingRequest createProjectBuildingRequest() { DefaultProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(mavenSession.getProjectBuildingRequest()); buildingRequest.setRemoteRepositories(project.getRemoteArtifactRepositories()); return buildingRequest; } @Override public VersionRangeRequest createVersionRangeRequest(Artifact artifact) { checkNotNull(artifact, "artifact is null"); return new VersionRangeRequest(artifact, project.getRemoteProjectRepositories(), ""); } @Override public List getExclusions() { return Arrays.asList(exclusions); } @Override public boolean isUnresolvedSystemArtifactsFailBuild() { return unresolvedSystemArtifactsFailBuild; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy