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

org.codehaus.mojo.versions.DisplayExtensionUpdatesMojo Maven / Gradle / Ivy

Go to download

The Versions Maven Plugin is used when you want to manage the versions of artifacts in a project's POM.

The newest version!
package org.codehaus.mojo.versions;

/*
 * Copyright MojoHaus and Contributors
 * 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.
 */

import javax.inject.Inject;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.TransformerException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Extension;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.wagon.Wagon;
import org.codehaus.mojo.versions.api.ArtifactVersions;
import org.codehaus.mojo.versions.api.PomHelper;
import org.codehaus.mojo.versions.api.Segment;
import org.codehaus.mojo.versions.api.VersionRetrievalException;
import org.codehaus.mojo.versions.api.recording.ChangeRecorder;
import org.codehaus.mojo.versions.filtering.DependencyFilter;
import org.codehaus.mojo.versions.filtering.WildcardMatcher;
import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader;
import org.codehaus.mojo.versions.utils.CoreExtensionUtils;
import org.codehaus.mojo.versions.utils.DependencyBuilder;
import org.codehaus.mojo.versions.utils.ExtensionBuilder;
import org.codehaus.mojo.versions.utils.ModelNode;
import org.codehaus.mojo.versions.utils.SegmentUtils;
import org.eclipse.aether.RepositorySystem;

import static java.util.Optional.of;
import static org.codehaus.mojo.versions.api.Segment.MAJOR;

/**
 * Displays all build and core extensions that have newer versions available.
 *
 * @author Andrzej Jarmoniuk
 * @since 2.15.0
 */
@Mojo(name = "display-extension-updates", aggregator = true, threadSafe = true)
public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo {

    // ------------------------------ FIELDS ------------------------------

    /**
     * The width to pad info messages.
     *
     * @since 1.0-alpha-1
     */
    private static final int INFO_PAD_SIZE = 72;

    /**
     * 

Specifies a comma-separated list of GAV patterns to consider * when looking for updates. If the trailing parts of the GAV are omitted, then can assume any value.

* *

The wildcard "*" can be used as the only, first, last or both characters in each token. * The version token does support version ranges.

* * Examples: {@code "mygroup:artifact:*"}, {@code "mygroup:artifact"}, {@code "mygroup"} * * @since 2.15.0 */ @Parameter(property = "extensionIncludes", defaultValue = WildcardMatcher.WILDCARD) private List extensionIncludes; /** *

Specifies a comma-separated list of GAV patterns to NOT consider * when looking for updates. If the trailing parts of the GAV are omitted, then can assume any value.

* *

This list is taken into account after {@link #extensionIncludes}

. * *

The wildcard "*" can be used as the only, first, last or both characters in each token. * The version token does support version ranges.

* * Examples: {@code "mygroup:artifact:*"}, {@code "mygroup:artifact"}, {@code "mygroup"} * * @since 2.15.0 */ @Parameter(property = "extensionExcludes") private List extensionExcludes; /** * Whether to allow the major version number to be changed. * * @since 2.15.0 */ @Parameter(property = "allowMajorUpdates", defaultValue = "true") private boolean allowMajorUpdates = true; /** *

Whether to allow the minor version number to be changed.

* *

Note: {@code false} also implies {@linkplain #allowMajorUpdates} * to be {@code false}

* * @since 2.15.0 */ @Parameter(property = "allowMinorUpdates", defaultValue = "true") private boolean allowMinorUpdates = true; /** *

Whether to allow the incremental version number to be changed.

* *

Note: {@code false} also implies {@linkplain #allowMajorUpdates} * and {@linkplain #allowMinorUpdates} to be {@code false}

* * @since 2.15.0 */ @Parameter(property = "allowIncrementalUpdates", defaultValue = "true") private boolean allowIncrementalUpdates = true; /** *

Whether to process core extensions. Default is {@code true}.

* @since 2.15.0 */ @Parameter(property = "processCoreExtensions", defaultValue = "true") private boolean processCoreExtensions = true; /** *

Whether to process build extensions. Default is {@code true}.

* @since 2.15.0 */ @Parameter(property = "processBuildExtensions", defaultValue = "true") private boolean processBuildExtensions = true; /** * If set to {@code false}, the plugin will not interpolate property values when looking for versions * to be changed, but will instead operate on raw model. * * @since 2.15.0 */ @Parameter(property = "interpolateProperties", defaultValue = "true") protected boolean interpolateProperties = true; /** * Whether to show additional information such as extensions that do not need updating. Defaults to false. * * @since 2.15.0 */ @Parameter(property = "verbose", defaultValue = "false") private boolean verbose; @Inject public DisplayExtensionUpdatesMojo( ArtifactHandlerManager artifactHandlerManager, RepositorySystem repositorySystem, Map wagonMap, Map changeRecorders) { super(artifactHandlerManager, repositorySystem, wagonMap, changeRecorders); } @Override public void execute() throws MojoExecutionException, MojoFailureException { logInit(); validateInput(); if (!processCoreExtensions && !processBuildExtensions) { getLog().info("Neither core nor build extensions are to be processed. Nothing to do."); return; } DependencyFilter includeFilter = DependencyFilter.parseFrom(extensionIncludes); DependencyFilter excludeFilter = DependencyFilter.parseFrom(extensionExcludes); Set dependencies; try { Stream extensions; if (processCoreExtensions) { extensions = CoreExtensionUtils.getCoreExtensions(project); } else { extensions = Stream.empty(); } if (processBuildExtensions) { if (!interpolateProperties) { extensions = Stream.concat( extensions, PomHelper.getChildModels(session.getCurrentProject(), getLog()).values().stream() .map(Model::getBuild) .filter(Objects::nonNull) .map(Build::getExtensions) .map(List::stream) .reduce(Stream::concat) .orElse(Stream.empty())); } else { List rawModels = getRawModels(); for (ModelNode node : rawModels) { if (node.getModel() == null) { // unlikely continue; } Map properties = new HashMap<>(); for (ModelNode p = node; p != null; p = p.getParent().orElse(null)) { p.getModel() .getProperties() .forEach((key, value) -> properties.putIfAbsent(String.valueOf(key), String.valueOf(value))); } extensions = Stream.concat( extensions, Optional.ofNullable(node.getModel().getBuild()) .map(Build::getExtensions) .orElse(Collections.emptyList()) .stream() .map(e -> ExtensionBuilder.newBuilder() .withGroupId(PomHelper.evaluate(e.getGroupId(), properties, getLog())) .withArtifactId( PomHelper.evaluate(e.getArtifactId(), properties, getLog())) .withVersion(PomHelper.evaluate(e.getVersion(), properties, getLog())) .build())); } } } dependencies = extensions .map(e -> DependencyBuilder.newBuilder() .withGroupId(e.getGroupId()) .withArtifactId(e.getArtifactId()) .withVersion(e.getVersion()) .build()) .filter(includeFilter::matchersMatch) .filter(excludeFilter::matchersDontMatch) .collect(Collectors.toSet()); } catch (IOException | XMLStreamException e) { throw new MojoExecutionException(e.getMessage()); } if (dependencies.isEmpty()) { getLog().info("Extensions set filtered by include- and exclude-filters is empty. Nothing to do."); return; } try { logUpdates(getHelper().lookupDependenciesUpdates(dependencies.stream(), true, true, allowSnapshots)); } catch (VersionRetrievalException e) { throw new MojoExecutionException(e.getMessage(), e); } } private List getRawModels() throws MojoFailureException { List rawModels; try { MutableXMLStreamReader pomReader = new MutableXMLStreamReader(getProject().getFile().toPath()); ModelNode rootNode = new ModelNode( PomHelper.getRawModel(pomReader.getSource(), getProject().getFile()), pomReader); rawModels = PomHelper.getRawModelTree(rootNode, getLog()); } catch (IOException | XMLStreamException | TransformerException e) { throw new MojoFailureException(e.getMessage(), e); } return rawModels; } private Optional calculateUpdateScope() { return of(SegmentUtils.determineUnchangedSegment( allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()) .map(Segment::minorTo) .orElse(MAJOR)); } private void logUpdates(Map updates) { List withUpdates = new ArrayList<>(); List usingCurrent = new ArrayList<>(); for (ArtifactVersions versions : updates.values()) { String left = " " + ArtifactUtils.versionlessKey(versions.getArtifact()) + " "; final String current; ArtifactVersion latest; if (versions.getCurrentVersion() != null) { current = versions.getCurrentVersion().toString(); latest = versions.getNewestUpdateWithinSegment(calculateUpdateScope(), allowSnapshots); } else { ArtifactVersion newestVersion = versions.getNewestVersion(versions.getArtifact().getVersionRange(), allowSnapshots); current = versions.getArtifact().getVersionRange().toString(); latest = newestVersion == null ? null : versions.getNewestUpdateWithinSegment(newestVersion, calculateUpdateScope(), allowSnapshots); if (latest != null && ArtifactVersions.isVersionInRange( latest, versions.getArtifact().getVersionRange())) { latest = null; } } String right = " " + (latest == null ? current : current + " -> " + latest); List t = latest == null ? usingCurrent : withUpdates; if (right.length() + left.length() + 3 > INFO_PAD_SIZE + getOutputLineWidthOffset()) { t.add(left + "..."); t.add(StringUtils.leftPad(right, INFO_PAD_SIZE + getOutputLineWidthOffset())); } else { t.add(StringUtils.rightPad(left, INFO_PAD_SIZE + getOutputLineWidthOffset() - right.length(), ".") + right); } } if (verbose) { if (usingCurrent.isEmpty()) { if (!withUpdates.isEmpty()) { logLine(false, "No extensions are using the newest version."); logLine(false, ""); } } else { logLine(false, "The following extensions are using the newest version:"); for (String s : usingCurrent) { logLine(false, s); } logLine(false, ""); } } if (withUpdates.isEmpty()) { if (!usingCurrent.isEmpty()) { logLine(false, "No extensions have newer versions."); logLine(false, ""); } } else { logLine(false, "The following extensions have newer versions:"); for (String withUpdate : withUpdates) { logLine(false, withUpdate); } logLine(false, ""); } } /** * @param pom the pom to update. * @see AbstractVersionsUpdaterMojo#update(MutableXMLStreamReader) * @since 1.0-alpha-1 */ @Override protected void update(MutableXMLStreamReader pom) { // do nothing } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy