diff --git a/.gitignore b/.gitignore index 2a91b82853..98c3aa27ba 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ target .project *.iml .idea +.vscode .checkstyle /.factorypath diff --git a/pom.xml b/pom.xml index 631be18c4a..8d1f89ac5d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,12 +5,12 @@ org.codehaus.mojo mojo-parent - 93 + 94 org.codehaus.mojo.versions versions - 2.19.1 + 2.20.1 pom Versions @@ -104,7 +104,7 @@ scm:git:https://github.com/mojohaus/versions.git scm:git:ssh://git@github.com/mojohaus/versions.git - 2.19.1 + 2.20.1 https://github.com/mojohaus/versions/tree/master @@ -137,7 +137,7 @@ ${maven-fluido-skin.version} 3.0.0 2.0.0 - 1.17.7 + 1.18.1 1.4.1 @@ -147,7 +147,7 @@ 0.75C - 2025-09-22T06:05:53Z + 2025-11-24T17:48:43Z @@ -262,7 +262,7 @@ org.codehaus.plexus plexus-i18n - 1.0.0 + 1.1.0 org.codehaus.plexus @@ -285,17 +285,17 @@ org.codehaus.plexus plexus-interactivity-api - 1.4 + 1.5.1 org.apache.commons commons-lang3 - 3.18.0 + 3.20.0 org.apache.maven.plugin-testing maven-plugin-testing-harness - 3.3.0 + 3.4.0 org.mockito @@ -353,17 +353,17 @@ commons-codec commons-codec - 1.19.0 + 1.20.0 commons-io commons-io - 2.20.0 + 2.21.0 org.codehaus.plexus plexus-archiver - 4.10.1 + 4.10.4 javax.inject diff --git a/versions-api/pom.xml b/versions-api/pom.xml index 0930cc1937..06db1de133 100644 --- a/versions-api/pom.xml +++ b/versions-api/pom.xml @@ -5,11 +5,25 @@ org.codehaus.mojo.versions versions - 2.19.1 + 2.20.1 versions-api Versions API Extension API for Versions Plugin + + + + + maven-javadoc-plugin + + + -Werror + + + + + + diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java index f1bc107c62..de631d39fa 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/DependencyVersionChange.java @@ -25,25 +25,29 @@ */ public interface DependencyVersionChange extends VersionChange { /** - * @return a groupId of changed item + * Returns the groupId of the dependency + * @return groupId of the dependency * @since 2.14.0 */ String getGroupId(); /** - * @return an ArtifactId of change item + * Returns the artifactId of the dependency + * @return artifactId of the dependency * @since 2.14.0 */ String getArtifactId(); /** - * @return an old version of changed item + * Returns the old version of the dependency + * @return old version the dependency * @since 2.14.0 */ String getOldVersion(); /** - * @return a new version of changed item + * Returns the new version of the dependency + * @return new version of the dependency * @since 2.14.0 */ String getNewVersion(); diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java index ebe60200c1..5452793434 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/change/PropertyVersionChange.java @@ -26,17 +26,20 @@ public interface PropertyVersionChange extends VersionChange { /** - * @return the property that has changed + * Returns the name of the property + * @return name of the property */ String getProperty(); /** - * @return the old value of the property + * Returns the old value of the property + * @return old value of the property */ String getOldValue(); /** - * @return the new value of the property + * Returns the new value of the property + * @return new value of the property */ String getNewValue(); } diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java index 16c2620bc3..3a266418e9 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/ChangeRecord.java @@ -28,7 +28,8 @@ */ public interface ChangeRecord { /** - * @return a details about changed item + * Returns the details about changed item + * @return details about changed item * @since 2.14.0 */ T getVersionChange(); diff --git a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java index ad89aa45d4..cab78ee020 100644 --- a/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java +++ b/versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/DependencyChangeRecord.java @@ -27,14 +27,32 @@ */ public interface DependencyChangeRecord extends ChangeRecord { /** - * Describe where version item is updated. + * Describes where version item is updated. */ enum ChangeKind { + /** + * A dependency change + */ DEPENDENCY("dependency-update"), + /** + * A dependency management change + */ DEPENDENCY_MANAGEMENT("dependency-management-update"), + /** + * A parent change + */ PARENT("parent-update"), + /** + * A plugin change + */ PLUGIN("plugin-update"), + /** + * A plugin management change + */ PLUGIN_MANAGEMENT("plugin-management-update"), + /** + * A dependency set by a property change + */ PROPERTY("property-update"); private final String label; @@ -43,12 +61,19 @@ enum ChangeKind { this.label = label; } + /** + * Returns the type of the change. + * @return type of the change + * + * @see ChangeKind + */ public String getLabel() { return label; } } /** + * Returns the version item change kind * @return a version item change kind * @since 2.14.0 */ diff --git a/versions-common/pom.xml b/versions-common/pom.xml index 08dd527f09..2b7fc64f0c 100644 --- a/versions-common/pom.xml +++ b/versions-common/pom.xml @@ -4,7 +4,7 @@ org.codehaus.mojo.versions versions - 2.19.1 + 2.20.1 versions-common @@ -163,14 +163,16 @@ + maven-javadoc-plugin - - org.codehaus.mojo.versions.model, - org.codehaus.mojo.versions.model.io.stax, - org.codehaus.mojo.versions.utils + all,-missing + + -quiet + + diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java index 3b53b82304..c47930e1a3 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java @@ -58,6 +58,19 @@ public abstract class AbstractVersionDetails implements VersionDetails { Pattern.compile("(?i)(?:.*[-.](alpha|a|beta|b|milestone|m|preview|rc)" + "[-.]?(\\d{0,2}[a-z]?|\\d{6}\\.\\d{4})|\\d{8}(?:\\.?\\d{6})?)$"); + /** + * Checks if the given version string represents a pre-release version. + * Pre-release versions include alpha, beta, milestone, preview, and release candidate versions. + * + * @param version the version string to check + * @return true if the version is a pre-release version, false otherwise + * + * @since 2.20.0 + */ + public static boolean isPreReleaseVersion(String version) { + return version != null && PREVIEW_PATTERN.matcher(version).matches(); + } + /** * Current version of the dependency artifact. * @@ -75,6 +88,9 @@ public abstract class AbstractVersionDetails implements VersionDetails { */ protected boolean verboseDetail = true; + /** + * Creates a new, empty instance. + */ protected AbstractVersionDetails() {} /** @@ -104,6 +120,7 @@ protected Optional getSelectedRestriction(ArtifactVersion selectedV return Optional.ofNullable(getCurrentVersionRange()) .map(VersionRange::getRestrictions) .flatMap(r -> r.stream() + .filter(rr -> rr.getLowerBound() != null || rr.getUpperBound() != null) .filter(rr -> rr.containsVersion(selectedVersion)) .findAny()); } @@ -321,7 +338,16 @@ public final ArtifactVersion[] getAllUpdates(Optional updateScope, bool @Override public final ArtifactVersion[] getAllUpdates(boolean includeSnapshots) { - return getAllUpdates((VersionRange) null, includeSnapshots); + ArtifactVersion[] updates = getAllUpdates((VersionRange) null, includeSnapshots); + if (getCurrentVersion() == null) { + ArtifactVersion lowerBound = getHighestLowerBound(null); + return Arrays.stream(updates) + .filter(v -> !getCurrentVersionRange().containsVersion(v)) + .filter(v -> v.compareTo(lowerBound) > 0) + .toArray(ArtifactVersion[]::new); + } else { + return updates; + } } @Override diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactAssociation.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactAssociation.java index bd673f26a9..533e1d5109 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactAssociation.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactAssociation.java @@ -22,18 +22,22 @@ import org.apache.maven.artifact.Artifact; /** - * Created by IntelliJ IDEA. - * + * An association between a property and an artifact. + *

+ * This is used to track which properties are associated with which artifacts so that when + * a property is updated the correct artifacts can be updated. * @author Stephen Connolly * @since 1.0-alpha-3 */ public interface ArtifactAssociation extends Comparable { /** - * @return whether the current association uses plugin repositories + * Tells whether the current association uses plugin repositories + * @return {@code true} if the current association uses plugin repositories */ boolean isUsePluginRepositories(); /** + * Returns the artifact associated with the property * @return associated artifact */ Artifact getArtifact(); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactVersions.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactVersions.java index 434d18f10c..17c536af9c 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactVersions.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/ArtifactVersions.java @@ -25,6 +25,8 @@ import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; +import java.util.function.Predicate; +import java.util.stream.Collectors; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.maven.artifact.Artifact; @@ -35,6 +37,8 @@ /** * Holds the results of a search for versions of an artifact. + *

+ * Includes the artifact itself (which holds the current version and version range) and the list of available versions. * * @author Stephen Connolly * @since 1.0-alpha-3 @@ -55,7 +59,8 @@ public class ArtifactVersions extends AbstractVersionDetails implements Comparab private final SortedSet versions; /** - * Creates a new {@link ArtifactVersions} instance. + * Creates a new {@link ArtifactVersions} instance given the artifact and a list of {@link ArtifactVersion} + * objects. * * @param artifact The artifact. * @param versions The versions. @@ -69,6 +74,26 @@ public ArtifactVersions(Artifact artifact, List versions) { setCurrentVersionRange(artifact.getVersionRange()); } + /** + *

Creates a new {@link ArtifactVersions} instance from the current instance using a filter predicate, + * matching version strings allowing to select versions which can remain in the resulting list of versions.

+ *

The filtering operation uses a shallow copy of the version elements. Also, the underlying artifact + * refers to the same {@link Artifact} object as the original.

+ * @param versionFilter a {@link Predicate}, saying which artifact versions of the original + * should be present in the newly created object + * @return a new instance with versions filtered by the predicate + * @since 2.20.0 + */ + public ArtifactVersions filter(Predicate versionFilter) { + ArtifactVersions result = new ArtifactVersions( + artifact, + versions.stream().filter(v -> versionFilter.test(v.toString())).collect(Collectors.toList())); + if (!versionFilter.test(result.artifact.getVersion())) { + result.setCurrentVersion((ArtifactVersion) null); + } + return result; + } + /** * Creates a new {@link ArtifactVersions} instance as shallow copy of the other * @@ -82,6 +107,7 @@ public ArtifactVersions(ArtifactVersions other) { setCurrentVersionRange(other.getCurrentVersionRange()); } + @Override public int compareTo(ArtifactVersions that) { return this == that ? 0 diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultArtifactAssociation.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultArtifactAssociation.java index 278b083bf4..5366c454ac 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultArtifactAssociation.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultArtifactAssociation.java @@ -25,10 +25,11 @@ import org.apache.maven.artifact.ArtifactUtils; /** - * Created by IntelliJ IDEA. - * - * @author connollys - * @since Aug 6, 2009 9:23:13 AM + * An association between a property and an artifact. + *

+ * This is used to track which properties are associated with which artifacts so that when + * a property is updated the correct artifacts can be updated. + * @author Stephen Connolly */ final class DefaultArtifactAssociation implements ArtifactAssociation { private final Artifact artifact; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java index c920919a87..89c0f5fc24 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java @@ -29,6 +29,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.SortedMap; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.ExecutionException; @@ -249,15 +250,42 @@ public void resolveArtifact(Artifact artifact, boolean usePluginRepositories) th } } - public Map lookupDependenciesUpdates( + @Override + public ArtifactVersions resolveArtifactVersions( + Artifact artifact, boolean usePluginRepositories, boolean useProjectRepositories) + throws VersionRetrievalException { + return lookupArtifactVersions(artifact, null, usePluginRepositories, !usePluginRepositories); + } + + @Override + public SortedMap resolveDependencyVersions( + Collection dependencies, boolean usePluginRepositories, boolean useProjectRepositories) + throws VersionRetrievalException { + return lookupDependenciesUpdates(dependencies.stream(), usePluginRepositories, useProjectRepositories, true); + } + + @Override + public PluginUpdatesDetails resolvePluginVersions(Plugin plugin) throws VersionRetrievalException { + return lookupPluginUpdates(plugin, true); + } + + @Override + public SortedMap resolvePluginVersions(Collection plugins) + throws VersionRetrievalException { + return lookupPluginsUpdates(plugins.stream(), true); + } + + @Override + public SortedMap lookupDependenciesUpdates( Stream dependencies, boolean usePluginRepositories, boolean useProjectRepositories, boolean allowSnapshots) throws VersionRetrievalException { + @SuppressWarnings("resource") ExecutorService executor = Executors.newFixedThreadPool(LOOKUP_PARALLEL_THREADS); try { - Map dependencyUpdates = new TreeMap<>(DependencyComparator.INSTANCE); + SortedMap dependencyUpdates = new TreeMap<>(DependencyComparator.INSTANCE); List>> futures = dependencies .map(dependency -> executor.submit(() -> new ImmutablePair<>( dependency, @@ -303,11 +331,12 @@ public ArtifactVersions lookupDependencyUpdates( } @Override - public Map lookupPluginsUpdates(Stream plugins, boolean allowSnapshots) + public SortedMap lookupPluginsUpdates(Stream plugins, boolean allowSnapshots) throws VersionRetrievalException { + @SuppressWarnings("resource") ExecutorService executor = Executors.newFixedThreadPool(LOOKUP_PARALLEL_THREADS); try { - Map pluginUpdates = new TreeMap<>(PluginComparator.INSTANCE); + SortedMap pluginUpdates = new TreeMap<>(PluginComparator.INSTANCE); List>> futures = plugins.map( p -> executor.submit(() -> new ImmutablePair<>(p, lookupPluginUpdates(p, allowSnapshots)))) .collect(Collectors.toList()); @@ -354,7 +383,7 @@ public Map getVersionPropertiesMap(VersionProperties Map properties = new HashMap<>(); // Populate properties map from request if (request.getPropertyDefinitions() != null) { - Arrays.stream(request.getPropertyDefinitions()).forEach(p -> properties.put(p.getName(), p)); + request.getPropertyDefinitions().forEach(p -> properties.put(p.getName(), p)); } Map builders = new HashMap<>(); @@ -498,33 +527,66 @@ public static class Builder { private PomHelper pomHelper; + /** + * Creates a new instance + */ public Builder() {} + /** + * Provides the {@link Log} instance + * @param log {@link Log} instance + * @return {@link Builder} instance + */ public Builder withLog(Log log) { this.log = log; return this; } + /** + * Provides the {@link MavenSession} instance + * @param mavenSession {@link MavenSession} instance + * @return {@link Builder} instance + */ public Builder withMavenSession(MavenSession mavenSession) { this.mavenSession = mavenSession; return this; } + /** + * Provides the {@link RepositorySystem} instance + * @param repositorySystem {@link RepositorySystem} instance + * @return {@link Builder} instance + */ public Builder withRepositorySystem(RepositorySystem repositorySystem) { this.repositorySystem = repositorySystem; return this; } + /** + * Provides the {@link RuleService} instance + * @param ruleService {@link RuleService} instance + * @return {@link Builder} instance + */ public Builder withRuleService(RuleService ruleService) { this.ruleService = ruleService; return this; } + /** + * Provides the {@link ArtifactFactory} instance + * @param artifactFactory {@link ArtifactFactory} instance + * @return {@link Builder} instance + */ public Builder withArtifactFactory(ArtifactFactory artifactFactory) { this.artifactFactory = artifactFactory; return this; } + /** + * Provides the {@link PomHelper} instance + * @param pomHelper {@link PomHelper} instance + * @return {@link Builder} instance + */ public Builder withPomHelper(PomHelper pomHelper) { this.pomHelper = pomHelper; return this; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/IgnoreVersionHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/IgnoreVersionHelper.java index 494d3b9ca3..b10485cd74 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/IgnoreVersionHelper.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/IgnoreVersionHelper.java @@ -16,12 +16,11 @@ */ import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.Optional; import java.util.function.BiFunction; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; @@ -41,16 +40,43 @@ static class IgnoreVersionException extends RuntimeException { } } - public static final List VALID_TYPES = Collections.unmodifiableList( - Arrays.asList(IgnoreVersion.TYPE_EXACT, IgnoreVersion.TYPE_REGEX, IgnoreVersion.TYPE_RANGE)); + /** + * Provides an instance of a list of valid types of {@link IgnoreVersion} + */ + public static final List VALID_TYPES = Arrays.stream(IgnoreVersionType.values()) + .map(IgnoreVersionType::getType) + .collect(Collectors.toList()); + + public enum IgnoreVersionType { + TYPE_EXACT(IgnoreVersion.TYPE_EXACT, IgnoreVersionHelper::isVersionIgnoredExact), + TYPE_REGEX(IgnoreVersion.TYPE_REGEX, IgnoreVersionHelper::isVersionIgnoredRegex), + TYPE_RANGE(IgnoreVersion.TYPE_RANGE, IgnoreVersionHelper::isVersionIgnoredRange); + + private final String type; + + private final BiFunction predicate; - private static final Map> VERSION_MATCHERS; + IgnoreVersionType(String type, BiFunction predicate) { + this.type = type; + this.predicate = predicate; + } + + public String getType() { + return type; + } + + public BiFunction getPredicate() { + return predicate; + } - static { - VERSION_MATCHERS = new HashMap<>(); - VERSION_MATCHERS.put(IgnoreVersion.TYPE_EXACT, IgnoreVersionHelper::isVersionIgnoredExact); - VERSION_MATCHERS.put(IgnoreVersion.TYPE_REGEX, IgnoreVersionHelper::isVersionIgnoredRegex); - VERSION_MATCHERS.put(IgnoreVersion.TYPE_RANGE, IgnoreVersionHelper::isVersionIgnoredRange); + public static Optional forType(String type) { + for (IgnoreVersionType v : IgnoreVersionType.values()) { + if (v.getType().equals(type)) { + return Optional.of(v); + } + } + return Optional.empty(); + } } private IgnoreVersionHelper() {} @@ -59,29 +85,47 @@ private IgnoreVersionHelper() {} * Check if type for given ignoredVersion is valid. * * @param ignoreVersion an ignored version to check - * @return true if type is valid + * @return {@code true} if type is valid */ public static boolean isValidType(IgnoreVersion ignoreVersion) { - return VALID_TYPES.contains(ignoreVersion.getType()); + return IgnoreVersionType.forType(ignoreVersion.getType()).isPresent(); + } + + /** + * Check if the provided version is ignored by the provided {@link IgnoreVersion} instance + * + * @param v version string to be checked + * @param ignoreVersion {@link IgnoreVersion} instance providing the filter + * @return {@code true} if the provided version is ignored + */ + public static boolean isVersionIgnored(String v, IgnoreVersion ignoreVersion) { + return IgnoreVersionType.forType(ignoreVersion.getType()) + .map(t -> t.getPredicate().apply(v, ignoreVersion)) + .orElseThrow(() -> new IllegalArgumentException("Invalid version type: " + ignoreVersion.getType())); } - public static boolean isVersionIgnored(Version version, IgnoreVersion ignoreVersion) { - return VERSION_MATCHERS.get(ignoreVersion.getType()).apply(version, ignoreVersion); + /** + * Check if the provided version is ignored by the provided {@link IgnoreVersion} instance + * + * @param v version string to be checked + * @param ignoreVersion {@link IgnoreVersion} instance providing the filter + * @return {@code true} if the provided version is ignored + */ + public static boolean isVersionIgnored(Version v, IgnoreVersion ignoreVersion) { + return isVersionIgnored(v.toString(), ignoreVersion); } - private static boolean isVersionIgnoredExact(Version version, IgnoreVersion ignoreVersion) { - return ignoreVersion.getVersion().equals(version.toString()); + private static boolean isVersionIgnoredExact(String v, IgnoreVersion ignoreVersion) { + return ignoreVersion.getVersion().equals(v); } - private static boolean isVersionIgnoredRegex(Version version, IgnoreVersion ignoreVersion) { - return Pattern.compile(ignoreVersion.getVersion()) - .matcher(version.toString()) - .matches(); + private static boolean isVersionIgnoredRegex(String v, IgnoreVersion ignoreVersion) { + return Pattern.compile(ignoreVersion.getVersion()).matcher(v).matches(); } - private static boolean isVersionIgnoredRange(Version version, IgnoreVersion ignoreVersion) { + private static boolean isVersionIgnoredRange(String v, IgnoreVersion ignoreVersion) { try { - ArtifactVersion aVersion = ArtifactVersionService.getArtifactVersion(version.toString()); + ArtifactVersion aVersion = ArtifactVersionService.getArtifactVersion(v); VersionRange versionRange = VersionRange.createFromVersionSpec(ignoreVersion.getVersion()); if (versionRange.hasRestrictions()) { return versionRange.containsVersion(aVersion); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PluginUpdatesDetails.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PluginUpdatesDetails.java index fefd30b51f..3773d6c87c 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PluginUpdatesDetails.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PluginUpdatesDetails.java @@ -33,11 +33,17 @@ /** * Details of a plugin's updates. */ -public class PluginUpdatesDetails extends ArtifactVersions { +public class PluginUpdatesDetails extends ArtifactVersions implements Comparable { private final Map dependencyVersions; private final boolean includeSnapshots; + /** + * Creates a new instance + * @param artifactVersions {@link ArtifactVersion} instance + * @param dependencyVersions map of dependencies and available versions + * @param includeSnapshots whether snapshots should be included + */ public PluginUpdatesDetails( ArtifactVersions artifactVersions, Map dependencyVersions, @@ -50,14 +56,27 @@ public PluginUpdatesDetails( this.includeSnapshots = includeSnapshots; } + /** + * Returns whether snapshots should be considered in version searches + * @return {@code true} if snapshots are included in version searches + */ public boolean isIncludeSnapshots() { return includeSnapshots; } + /** + * Returns a map of dependencies and associated available dependency versions + * @return map of dependencies and associated available dependency versions + */ public Map getDependencyVersions() { return dependencyVersions; } + /** + * Merges in the provided map of dependencies and associated available dependency versions + * @param dependencyVersions map of dependencies and associated available dependency versions to be merged + * with the map in the {@link PluginUpdatesDetails} instance + */ public void addDependencyVersions(Map dependencyVersions) { this.dependencyVersions.putAll(dependencyVersions); } @@ -107,14 +126,20 @@ public boolean equals(Object o) { && super.equals(o); } + @Override public int hashCode() { return Objects.hash(getArtifact(), Arrays.hashCode(getVersions(true)), includeSnapshots, dependencyVersions); } // added an arbitrary comparison just to be able to differentiate objects having different includeSnapshots // and dependencyVersions while their super.compareTo() returns 0 + @Override @SuppressWarnings("checkstyle:InnerAssignment") - public int compareTo(PluginUpdatesDetails that) { + public int compareTo(ArtifactVersions other) { + if (!(other instanceof PluginUpdatesDetails)) { + return -1; + } + PluginUpdatesDetails that = (PluginUpdatesDetails) other; int r; return (r = super.compareTo(that)) != 0 ? r diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java index a59d3845c9..135f58fd9a 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java @@ -21,7 +21,6 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import javax.xml.transform.TransformerException; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -97,7 +96,13 @@ import static org.codehaus.mojo.versions.api.PomHelper.Marks.PARENT_START; import static org.codehaus.mojo.versions.api.PomHelper.Marks.START; +/** + * A utility class for parsing and performing operations on pom.xml files + */ public class PomHelper { + /** + * Static instance of the {@code org.apache.maven.plugins} string + */ public static final String APACHE_MAVEN_PLUGINS_GROUPID = "org.apache.maven.plugins"; private static final Set IMPLICIT_PATHS = new HashSet<>(Arrays.asList( @@ -140,6 +145,9 @@ enum Marks { /** * Creates a new instance + * + * @param artifactFactory {@link ArtifactFactory} instance + * @param expressionEvaluator {@link ExpressionEvaluator} instance */ public PomHelper(ArtifactFactory artifactFactory, ExpressionEvaluator expressionEvaluator) { this.artifactFactory = artifactFactory; @@ -177,7 +185,7 @@ public static Model getRawModel(File moduleProjectFile) throws IOException { * Gets the current raw model before any interpolation what-so-ever. * * @param modelString a string containing the raw model - * @param modelPath the File containing the model + * @param modelPath the File containing the model * @return The raw model. * @throws IOException if the file is not found or if the file does not parse. */ @@ -421,7 +429,7 @@ static T executeOnPatternFound( * * @param pom The pom. * @return the project version or null if the project version is not defined (i.e. inherited from - * parent version). + * parent version). * @throws XMLStreamException if something went wrong. */ public static String getProjectVersion(final MutableXMLStreamReader pom) throws XMLStreamException { @@ -795,7 +803,8 @@ static Map getRawModelWithParents(MavenProject project) thr /** * Examines the project to find any properties which are associated with versions of artifacts in the project. * - * @param helper {@link VersionsHelper} instance + * @param resolverAdapter {@link ResolverAdapter} instance + * @param log {@link Log} instance * @param project The project to examine. * @param includeParent whether parent POMs should be included * @return An array of properties that are associated within the project. @@ -804,7 +813,7 @@ static Map getRawModelWithParents(MavenProject project) thr * @since 1.0-alpha-3 */ public PropertyVersionsBuilder[] getPropertyVersionsBuilders( - VersionsHelper helper, Log log, MavenProject project, boolean includeParent) + ResolverAdapter resolverAdapter, Log log, MavenProject project, boolean includeParent) throws ExpressionEvaluationException, IOException { Map reactorModels = includeParent @@ -816,8 +825,8 @@ public PropertyVersionsBuilder[] getPropertyVersionsBuilders( Map propertiesMap = new TreeMap<>(); reactorModels.values().forEach(model -> { - processProfiles(helper, log, propertiesMap, model, activeProfileIds); - putPropertiesIfAbsent(helper, log, propertiesMap, null, model.getProperties()); + processProfiles(resolverAdapter, log, propertiesMap, model, activeProfileIds); + putPropertiesIfAbsent(resolverAdapter, log, propertiesMap, null, model.getProperties()); }); // Process the project and its parent hierarchy @@ -838,7 +847,7 @@ public PropertyVersionsBuilder[] getPropertyVersionsBuilders( } private void processProfiles( - VersionsHelper helper, + ResolverAdapter resolverAdapter, Log log, Map propertiesMap, Model model, @@ -848,7 +857,8 @@ private void processProfiles( .filter(profile -> activeProfileIds.contains(profile.getId())) .forEach(profile -> { try { - putPropertiesIfAbsent(helper, log, propertiesMap, profile.getId(), profile.getProperties()); + putPropertiesIfAbsent( + resolverAdapter, log, propertiesMap, profile.getId(), profile.getProperties()); processDependencies( propertiesMap, profile.getDependencyManagement(), profile.getDependencies()); processBuild(propertiesMap, profile.getBuild()); @@ -909,9 +919,9 @@ private void processReporting(Map propertiesMap * Takes a list of {@link org.apache.maven.model.Plugin} instances and adds associations to properties used to * define versions of the plugin artifact or any of the plugin dependencies specified in the pom. * - * @param result The map of {@link org.codehaus.mojo.versions.api.PropertyVersionsBuilder} keyed by - * property name. - * @param plugins The list of {@link org.apache.maven.model.Plugin}. + * @param result The map of {@link org.codehaus.mojo.versions.api.PropertyVersionsBuilder} keyed by + * property name. + * @param plugins The list of {@link org.apache.maven.model.Plugin}. * @throws ExpressionEvaluationException if an expression cannot be evaluated. */ private void addPluginAssociations(Map result, List plugins) @@ -1067,7 +1077,7 @@ private static void addBounds(PropertyVersionsBuilder builder, String rawVersion } private void putPropertiesIfAbsent( - VersionsHelper helper, + ResolverAdapter resolverAdapter, Log log, Map result, String profileId, @@ -1075,7 +1085,7 @@ private void putPropertiesIfAbsent( ofNullable(properties) .map(Properties::stringPropertyNames) .ifPresent(propertyNames -> propertyNames.forEach(propertyName -> result.putIfAbsent( - propertyName, new PropertyVersionsBuilder(helper, profileId, propertyName, log)))); + propertyName, new PropertyVersionsBuilder(resolverAdapter, profileId, propertyName, log)))); } /** @@ -1261,7 +1271,7 @@ public static List getRawModelTree(ModelNode rootNode, Log logger) th return new ModelNode(rootNode, getRawModel(pom.getSource(), pomFile.toFile()), pom); } catch (IOException e) { throw new UncheckedIOException("Could not open " + pomFile, e); - } catch (XMLStreamException | TransformerException e) { + } catch (XMLStreamException e) { throw new RuntimeException("Could not parse " + pomFile, e); } }) @@ -1276,7 +1286,7 @@ public static List getRawModelTree(ModelNode rootNode, Log logger) th * @param propertyName name of the property to be found * @param node model tree node at which the search should be started * @return {@link Optional} object containing the model tree node containing the closest - * property definition, or {@link Optional#empty()} if none has been found + * property definition, or {@link Optional#empty()} if none has been found */ public static Optional findProperty(String propertyName, ModelNode node) { if (ofNullable(node.getModel().getProperties()) @@ -1413,8 +1423,9 @@ public static int getReactorParentCount(Map reactor, Model model) { * Reads an XML from the given InputStream. * * @param inputStream The input stream to read. - * @return Pair<String, Charset> The (mutable) content of the file with the charset of the file - * @throws java.io.IOException when things go wrong. + * @return a pair representing the (mutable) content of the file with the charset of the file + * @throws IOException thrown if it's not possible to read from the provided input stream + * @throws XMLStreamException thrown if there are problems parsing the provided input stream */ public static Pair readXml(InputStream inputStream) throws IOException, XMLStreamException { try (BufferedInputStream buffer = new BufferedInputStream(inputStream)) { @@ -1441,10 +1452,10 @@ public static Pair readXml(InputStream inputStream) throws IOEx * * @param file The file to read. * @return Pair<String, Charset> The contents of the file with the charset of the file - * @throws java.io.IOException when things go wrong. + * @throws IOException thrown on problems with reading from the file + * @throws XMLStreamException thrown if there are problems parsing the file */ - public static Pair readXml(File file) - throws IOException, XMLStreamException, TransformerException { + public static Pair readXml(File file) throws IOException, XMLStreamException { try (InputStream is = Files.newInputStream(file.toPath())) { return readXml(is); } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java index 535fd3263f..f58d3e42df 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/Property.java @@ -81,6 +81,7 @@ public class Property { * When {@link #searchReactor} is {@code true} and a property version can be entirely satisfied from the * reactor and this setting is {@code true} then the reactor version will be specified irrespective of any * other settings (including {@link #isBanSnapshots}). + * * @since 1.0-alpha-3 */ private boolean preferReactor; @@ -118,13 +119,17 @@ public Property(String name) { } /** - * @return name + * Returns the property name + * + * @return name of the property */ public String getName() { return name; } /** + * Sets the name of the property + * * @param name name to be set */ public void setName(String name) { @@ -132,6 +137,8 @@ public void setName(String name) { } /** + * Returns the property version + * * @return version */ public String getVersion() { @@ -139,6 +146,8 @@ public String getVersion() { } /** + * Sets the property version + * * @param version version to be set */ public void setVersion(String version) { @@ -146,14 +155,18 @@ public void setVersion(String version) { } /** - * @return if properties linking versions should be auto-detected or not + * Whether properties linking versions should be auto-detected or not + * + * @return {@code true} if properties linking versions should be auto-detected or not */ public boolean isAutoLinkDependencies() { return autoLinkDependencies; } /** - * @param autoLinkDependencies whether properties indicating dependency versions should + * Specifies whether properties indicating dependency versions should be linked automatically + * + * @param autoLinkDependencies {@code true} if properties indicating dependency versions should * be linked automatically */ public void setAutoLinkDependencies(boolean autoLinkDependencies) { @@ -163,6 +176,7 @@ public void setAutoLinkDependencies(boolean autoLinkDependencies) { /** * Dependencies that must be available for this property. If {@link #isAutoLinkDependencies} is {@code true} then * these dependencies will be considered in addition to the automatically linked dependencies. + * * @return dependencies */ public Dependency[] getDependencies() { @@ -172,6 +186,7 @@ public Dependency[] getDependencies() { /** * Dependencies that must be available for this property. If {@link #isAutoLinkDependencies} is {@code true} then * these dependencies will be considered in addition to the automatically linked dependencies. + * * @param dependencies to be set */ public void setDependencies(Dependency[] dependencies) { @@ -179,13 +194,17 @@ public void setDependencies(Dependency[] dependencies) { } /** - * @return whether reactor should be searched for the artifact version + * Says whether reactor should be searched for the artifact version + * + * @return {@code true} if reactor should be searched for the artifact version */ public boolean isSearchReactor() { return searchReactor; } /** + * Specifies whether reactor should be searched for the artifact version + * * @param searchReactor whether reactor should be searched for the artifact version */ public void setSearchReactor(boolean searchReactor) { @@ -193,30 +212,54 @@ public void setSearchReactor(boolean searchReactor) { } /** - * @return when {@link #searchReactor} is {@code true} and a property version can be entirely satisfied from the - * reactor and this setting is {@code true} then the reactor version will be specified irrespective of any + * Says whether, when {@link #searchReactor} is {@code true} and a property version can be entirely satisfied + * from the reactor and this setting is {@code true} then the reactor version will be specified irrespective of any * other settings (including {@link #isBanSnapshots}). + * @return provided value */ public boolean isPreferReactor() { return preferReactor; } + /** + * Specifies whether, when {@link #searchReactor} is {@code true} and a property version can be entirely satisfied + * from the reactor and this setting is {@code true} then the reactor version will be specified irrespective of any + * other settings (including {@link #isBanSnapshots}). + * + * @param preferReactor required value + */ public void setPreferReactor(boolean preferReactor) { this.preferReactor = preferReactor; } + /** + * Specifies whether snapshots should not be considered + * @return {@code true} if snapshots should not be considered + */ public boolean isBanSnapshots() { return banSnapshots; } + /** + * Specifies whether snapshots should not be considered + * @param banSnapshots {@code true} if snapshots should not be considered + */ public void setBanSnapshots(boolean banSnapshots) { this.banSnapshots = banSnapshots; } + /** + * Returns the value of the property + * @return value of the property + */ public String getValue() { return value; } + /** + * Sets the value of the property + * @param value property value to be set + */ public void setValue(String value) { this.value = value; } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersions.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersions.java index bad5d0d8b3..1a2b0b1277 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersions.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersions.java @@ -77,6 +77,10 @@ public class PropertyVersions extends AbstractVersionDetails { this.resolvedVersions = resolvedVersions; } + /** + * Returns an array of artifacts associated with the property + * @return an array of {@link Artifact} instances associated with the property + */ public ArtifactAssociation[] getAssociations() { return associations.toArray(new ArtifactAssociation[0]); } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersionsBuilder.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersionsBuilder.java index 2c9cbfa5f9..f8a0a3350f 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersionsBuilder.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/PropertyVersionsBuilder.java @@ -48,7 +48,7 @@ public class PropertyVersionsBuilder { private final String profileId; - private final Set associations; + private final Set associations = new TreeSet<>(); private final Map upperBounds = new LinkedHashMap<>(); @@ -56,7 +56,7 @@ public class PropertyVersionsBuilder { private final Log log; - private final VersionsHelper helper; + private final ResolverAdapter resolverAdapter; private ArtifactVersion currentVersion; @@ -65,18 +65,24 @@ public class PropertyVersionsBuilder { /** * Constructs a new {@link org.codehaus.mojo.versions.api.PropertyVersions}. * + * @param resolverAdapter {@link ResolverAdapter} instance * @param profileId The profileId. * @param name The property name. - * @param helper The {@link org.codehaus.mojo.versions.api.DefaultVersionsHelper}. + * @param log The {@link Log} instance. */ - PropertyVersionsBuilder(VersionsHelper helper, String profileId, String name, Log log) { - this.helper = helper; + PropertyVersionsBuilder(ResolverAdapter resolverAdapter, String profileId, String name, Log log) { this.profileId = profileId; this.name = name; - this.associations = new TreeSet<>(); this.log = log; + this.resolverAdapter = resolverAdapter; } + /** + * Provides the associated artifact + * @param artifact artifact associated with the property + * @param usePluginRepositories whether to use plugin repositories + * @return builder instance + */ public PropertyVersionsBuilder withAssociation(Artifact artifact, boolean usePluginRepositories) { associations.add(new DefaultArtifactAssociation(artifact, usePluginRepositories)); return this; @@ -105,18 +111,34 @@ public boolean isAssociated() { return !associations.isEmpty(); } + /** + *

Creates a new instance of {@link PropertyVersions}, based on the values provided to the builder. + * The object is a mutable view on a property along with all its associated dependencies or plugins.

+ *

The builder uses {@link ResolverAdapter} to resolve available versions for all associations.

+ * @return new {@link PropertyVersions} instance + * @throws VersionRetrievalException thrown if there are problems retrieving versions of artifacts linked + * with the property + */ public PropertyVersions build() throws VersionRetrievalException { - SortedSet resolvedVersions = resolveAssociatedVersions(helper, associations); + SortedSet resolvedVersions = resolveAssociatedVersions(associations); PropertyVersions instance = new PropertyVersions(profileId, name, log, associations, resolvedVersions); instance.setCurrentVersion(currentVersion); instance.setCurrentVersionRange(currentVersionRange); return instance; } + /** + * Returns the property name + * @return property name + */ public String getName() { return name; } + /** + * Returns the version range + * @return version range + */ public String getVersionRange() { if (lowerBounds.isEmpty() && upperBounds.isEmpty()) { return null; @@ -139,32 +161,75 @@ public String getVersionRange() { + (upperBound.map(Pair::getValue).orElse(false) ? ']' : ')'); } + /** + * Provides the lower bound of the property version and whether the lower bound should be included + * @param lowerBound lower bound of the property version + * @param includeLower whether the lower bound should be included + * @return builder instance + */ public PropertyVersionsBuilder withLowerBound(String lowerBound, boolean includeLower) { lowerBounds.compute(lowerBound, (__, oldValue) -> ofNullable(oldValue).orElse(true) && includeLower); return this; } + /** + * Provides the upper bound of the property version and whether the upper bound should be included + * @param upperBound upper bound of the property version + * @param includeUpper whether the upper bound should be included + * @return builder instance + */ public PropertyVersionsBuilder withUpperBound(String upperBound, boolean includeUpper) { upperBounds.compute(upperBound, (__, oldValue) -> ofNullable(oldValue).orElse(true) && includeUpper); return this; } + /** + * Provides the current version of the linked artifact + * @param currentVersion current version of the linked artifact + * @return builder instance + */ public PropertyVersionsBuilder withCurrentVersion(ArtifactVersion currentVersion) { this.currentVersion = currentVersion; return this; } + /** + * Provides the current version range of the linked artifact + * @param currentVersionRange current version range of the linked artifact + * @return builder instance + */ public PropertyVersionsBuilder withCurrentVersionRange(VersionRange currentVersionRange) { this.currentVersionRange = currentVersionRange; return this; } private SortedSet resolveAssociatedVersions( - VersionsHelper helper, Set associations) throws VersionRetrievalException { + ResolverAdapter resolverAdapter, Set associations) throws VersionRetrievalException { + SortedSet result = new TreeSet<>(); + for (ArtifactAssociation association : associations) { + ArtifactVersions artifactVersions = resolverAdapter.resolveArtifactVersions( + association.getArtifact(), + association.isUsePluginRepositories(), + !association.isUsePluginRepositories()); + List associatedVersions = Arrays.asList(artifactVersions.getVersions(true)); + if (result.isEmpty()) { + result.addAll(associatedVersions); + } else { + result.retainAll(associatedVersions); + } + } + return result; + } + + @Deprecated + private SortedSet resolveAssociatedVersions(Set associations) + throws VersionRetrievalException { SortedSet result = new TreeSet<>(); for (ArtifactAssociation association : associations) { - ArtifactVersions artifactVersions = - helper.lookupArtifactVersions(association.getArtifact(), association.isUsePluginRepositories()); + ArtifactVersions artifactVersions = resolverAdapter.resolveArtifactVersions( + association.getArtifact(), + association.isUsePluginRepositories(), + !association.isUsePluginRepositories()); List associatedVersions = Arrays.asList(artifactVersions.getVersions(true)); if (result.isEmpty()) { result.addAll(associatedVersions); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/ResolverAdapter.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/ResolverAdapter.java new file mode 100644 index 0000000000..d103bcee66 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/ResolverAdapter.java @@ -0,0 +1,90 @@ +package org.codehaus.mojo.versions.api; + +import java.util.Collection; +import java.util.SortedMap; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Plugin; + +/** + * A thin adapter over {@link org.eclipse.aether.RepositorySystem} to help + * discover available versions for provided artifacts. + * + * @since 2.20.0 + */ +public interface ResolverAdapter { + + /** + * Attempts to resolve the artifact. If the artifact cannot be resolved, an + * {@link ArtifactResolutionException} is thrown. + * + * @param artifact The artifact to resolve. + * @param usePluginRepositories whether to resolve from the plugin repositories or the regular repositories. + * @throws ArtifactResolutionException if resolution is unsuccessful + * @since 2.20.0 + */ + void resolveArtifact(Artifact artifact, boolean usePluginRepositories) throws ArtifactResolutionException; + + /** + * Returns all available versions of the specified artifact that are available in either the local repository, or + * the + * appropriate remote repositories. + * The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots, + * regardless of the version range specified in the artifact. + * + * @param artifact The artifact to look for versions of. + * @param usePluginRepositories {@code true} will consult the pluginRepositories + * @param useProjectRepositories {@code true} will consult regular project repositories + * @return The details of the available artifact versions. + * @throws VersionRetrievalException thrown if version resolution fails + * @since 2.15.0 + */ + ArtifactVersions resolveArtifactVersions( + Artifact artifact, boolean usePluginRepositories, boolean useProjectRepositories) + throws VersionRetrievalException; + + /** + *

Returns a sorted map of all possible updates per dependency. The map keys are sorted using + * {@link org.codehaus.mojo.versions.utils.DependencyComparator}, which boils down to sorting by + * and groupId:artifactId:classifier.

+ *

The returned map is sorted by {@code groupId:artifactId:classifier}.

+ *

Version retrieval is done in parallel, using {@code LOOKUP_PARALLEL_THREADS} threads.

+ * + * @param dependencies a collection of {@link Dependency} instances to look up. + * @param usePluginRepositories {@code true} will consult the pluginRepositories + * @param useProjectRepositories {@code true} will consult regular project repositories + * @return map containing the ArtifactVersions object per dependency sorted by groupId, artifactId, + * classifier + * @throws VersionRetrievalException thrown if a version cannot be retrieved + */ + SortedMap resolveDependencyVersions( + Collection dependencies, boolean usePluginRepositories, boolean useProjectRepositories) + throws VersionRetrievalException; + + /** + * Looks up the updates for a plugin. The resulting {@link org.codehaus.mojo.versions.api.PluginUpdatesDetails} + * instance will only contain versions that are newer than the current version of the plugin. + * + * @param plugin The {@link Plugin} instance to look up. + * @return The plugin update details. + * @throws VersionRetrievalException thrown if version resolution fails + * @since 1.0-beta-1 + */ + PluginUpdatesDetails resolvePluginVersions(Plugin plugin) throws VersionRetrievalException; + + /** + *

Looks up the updates for a set of plugins. The resulting + * {@link org.codehaus.mojo.versions.api.PluginUpdatesDetails} instance per plugin + * will only contain versions that are newer than the current version of the plugin.

+ *

The returned map is sorted by {@code groupId:artifactId:classifier}.

+ * + * @param plugins A collection of {@link Plugin} instances to look up. + * @return A map, keyed by plugin, with values of type {@link org.codehaus.mojo.versions.api.PluginUpdatesDetails}. + * @throws VersionRetrievalException thrown if version resolution fails + * @since 1.0-beta-1 + */ + SortedMap resolvePluginVersions(Collection plugins) + throws VersionRetrievalException; +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/Segment.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/Segment.java index 20ccf4d212..4a8592f722 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/Segment.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/Segment.java @@ -27,9 +27,21 @@ * @author Andrzej Jarmoniuk */ public enum Segment implements Comparable { + /** + * Major segment (0-based index 0) + */ MAJOR, + /** + * Minor segment (0-based index 1) + */ MINOR, + /** + * Incremental segment (0-based index 2) + */ INCREMENTAL, + /** + * Sub-incremental segment (0-based index 3) + */ SUBINCREMENTAL; /** @@ -41,6 +53,11 @@ public int value() { return ordinal(); } + /** + * Creates a segment from its 0-based index + * @param index 0-based index + * @return segment + */ public static Segment of(int index) { if (index < 0 || index > 3) { throw new IllegalArgumentException("Wrong segment index: " + index); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java index 23308ae049..fbec4181b7 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java @@ -27,9 +27,12 @@ import org.codehaus.mojo.versions.ordering.InvalidSegmentException; /** - * Created by IntelliJ IDEA. + * Describes the details of available versions for an artifact. * - * @author connollys + *

This interface provides methods to query available versions, check for specific versions, + * and retrieve the current version of the artifact.

+ * + * @author Stephen Connolly * @since 1.0-beta-1 */ public interface VersionDetails { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionRetrievalException.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionRetrievalException.java index 29f4f90b69..6f534240bd 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionRetrievalException.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionRetrievalException.java @@ -24,10 +24,11 @@ import org.apache.maven.artifact.Artifact; /** - * Exception thrown if version information cannot be retrieved + * Exception thrown if version information cannot be retrieved. */ public class VersionRetrievalException extends Exception { + /** The artifact for which version retrieval failed, may be {@code null}. */ private final Artifact artifact; /** diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java index bd2b778f6a..5bc525b8bf 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/VersionsHelper.java @@ -19,6 +19,7 @@ * under the License. */ +import java.util.List; import java.util.Map; import java.util.function.Predicate; import java.util.stream.Stream; @@ -37,12 +38,13 @@ * @author Stephen Connolly * @since 1.0-alpha-3 */ -public interface VersionsHelper { +public interface VersionsHelper extends ResolverAdapter { /** * Looks up the versions of the specified artifact that are available in either the local repository, or the * appropriate remote repositories. - * The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots. + * The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots, + * regardless of the version range specified in the artifact. * * @param artifact The artifact to look for versions of. * @param usePluginRepositories {@code true} will consult the pluginRepositories, while {@code false} will @@ -57,7 +59,8 @@ ArtifactVersions lookupArtifactVersions(Artifact artifact, boolean usePluginRepo /** * Looks up the versions of the specified artifact that are available in either the local repository, or the * appropriate remote repositories. - * The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots. + * The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots, + * regardless of the version range specified in the artifact. * * @param artifact The artifact to look for versions of. * @param versionRange versionRange to restrict the search, may be {@code null} @@ -74,7 +77,8 @@ ArtifactVersions lookupArtifactVersions( /** * Looks up the versions of the specified artifact that are available in either the local repository, or the * appropriate remote repositories. - * The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots. + * The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots, + * regardless of the version range specified in the artifact. * * @param artifact The artifact to look for versions of. * @param versionRange versionRange to restrict the search, may be {@code null} @@ -104,6 +108,8 @@ Map lookupDependenciesUpdates( /** * Returns a map of all possible updates per dependency. The lookup is done in parallel using * {@code LOOKUP_PARALLEL_THREADS} threads. + * The resulting {@link ArtifactVersions} instance per dependency will only contain versions that are newer + * than the current version of the dependency. * * @param dependencies stream of {@link Dependency} instances to look up. * @param usePluginRepositories Search the plugin repositories. @@ -120,7 +126,9 @@ Map lookupDependenciesUpdates( throws VersionRetrievalException; /** - * Creates an {@link org.codehaus.mojo.versions.api.ArtifactVersions} instance from a dependency. + * Creates an {@link org.codehaus.mojo.versions.api.ArtifactVersions} instance from a dependency + * The resulting {@link ArtifactVersions} instance will only contain versions that are newer than the current version + * of the dependency. * * @param dependency The dependency. * @param usePluginRepositories Search the plugin repositories. @@ -138,7 +146,8 @@ ArtifactVersions lookupDependencyUpdates( throws VersionRetrievalException; /** - * Looks up the updates for a set of plugins. + * Looks up the updates for a set of plugins. he resulting {@link org.codehaus.mojo.versions.api.PluginUpdatesDetails} instance per plugin + * will only contain versions that are newer than the current version of the plugin. * * @param plugins A stream of {@link Plugin} instances to look up. * @param allowSnapshots Include snapshots in the list of updates. @@ -150,7 +159,8 @@ Map lookupPluginsUpdates(Stream plugins, b throws VersionRetrievalException; /** - * Looks up the updates for a plugin. + * Looks up the updates for a plugin. The resulting {@link org.codehaus.mojo.versions.api.PluginUpdatesDetails} + * instance will only contain versions that are newer than the current version of the plugin. * * @param plugin The {@link Plugin} instance to look up. * @param allowSnapshots Include snapshots in the list of updates. @@ -164,6 +174,12 @@ Map lookupPluginsUpdates(Stream plugins, b * Returns a map of {@link org.codehaus.mojo.versions.api.PropertyVersions} values keyed by * {@link Property} instances consisting of the properties defined in the project which * are associated with version information. + *

+ * The associations can be defined explicitly via the property definitions, or + * inferred automatically if {@code autoLinkItems} is set to {@code true}. In the latter + * case, any property that matches the version of a dependency or plugin + * (and passes the {@code includeFilter} test, if provided) will be considered + * associated with that artifact. * * @param request {@link VersionPropertiesMapRequest} instance containing the arguments * @return a map of {@link org.codehaus.mojo.versions.api.PropertyVersions} values keyed by @@ -174,13 +190,14 @@ Map getVersionPropertiesMap(VersionPropertiesMapRequ throws MojoExecutionException; /** - * Argument builder class for - * {@link VersionsHelper#getVersionPropertiesMap(VersionPropertiesMapRequest)}. + * Argument builder class for {@link VersionsHelper#getVersionPropertiesMap(VersionPropertiesMapRequest)}. + *

+ * Instances of this class are used to collect parameters required to build the version properties map. */ class VersionPropertiesMapRequest { private MavenProject mavenProject; - private Property[] propertyDefinitions; + private List propertyDefinitions; private String includeProperties; @@ -192,6 +209,13 @@ class VersionPropertiesMapRequest { private Predicate includeFilter; + /** + * Deprecated no-arg constructor. Use {@link #builder()} instead. + * @deprecated use {@link #builder()} instead + */ + @Deprecated + public VersionPropertiesMapRequest() {} + /** * Returns the {@link MavenProject} object * @@ -206,7 +230,7 @@ protected MavenProject getMavenProject() { * * @return {@link Property} array */ - protected Property[] getPropertyDefinitions() { + protected List getPropertyDefinitions() { return propertyDefinitions; } @@ -258,9 +282,9 @@ protected boolean isAutoLinkItems() { } /** - * Returns a new {@link Builder} instance + * Create a new builder instance. * - * @return new {@link Builder} instance + * @return a fresh {@link Builder} */ public static Builder builder() { return new Builder(); @@ -272,7 +296,7 @@ public static Builder builder() { public static class Builder { private MavenProject mavenProject; - private Property[] propertyDefinitions; + private List propertyDefinitions; private String includeProperties; @@ -303,7 +327,7 @@ public Builder withMavenProject(MavenProject mavenProject) { * @param propertyDefinitions array of property definitions * @return {@link Builder} instance */ - public Builder withPropertyDefinitions(Property[] propertyDefinitions) { + public Builder withPropertyDefinitions(List propertyDefinitions) { this.propertyDefinitions = propertyDefinitions; return this; } @@ -384,7 +408,8 @@ public VersionPropertiesMapRequest build() { } /** - * Attempts to resolve the artifact. + * Attempts to resolve the artifact. If the artifact cannot be resolved, an + * {@link ArtifactResolutionException} is thrown. * * @param artifact The artifact to resolve. * @param usePluginRepositories whether to resolve from the plugin repositories or the regular repositories. diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/api/internal/DefaultResolverAdapter.java b/versions-common/src/main/java/org/codehaus/mojo/versions/api/internal/DefaultResolverAdapter.java new file mode 100644 index 0000000000..64d3bcd3d4 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/api/internal/DefaultResolverAdapter.java @@ -0,0 +1,230 @@ +package org.codehaus.mojo.versions.api.internal; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.RepositoryUtils; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.codehaus.mojo.versions.api.ArtifactVersions; +import org.codehaus.mojo.versions.api.PluginUpdatesDetails; +import org.codehaus.mojo.versions.api.ResolverAdapter; +import org.codehaus.mojo.versions.api.VersionRetrievalException; +import org.codehaus.mojo.versions.utils.ArtifactFactory; +import org.codehaus.mojo.versions.utils.ArtifactVersionService; +import org.codehaus.mojo.versions.utils.DependencyComparator; +import org.codehaus.mojo.versions.utils.PluginComparator; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.repository.RepositoryPolicy; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.resolution.VersionRangeRequest; +import org.eclipse.aether.resolution.VersionRangeResolutionException; + +import static java.util.Optional.of; +import static org.apache.maven.RepositoryUtils.toArtifact; + +public class DefaultResolverAdapter implements ResolverAdapter { + + private static final int LOOKUP_PARALLEL_THREADS = 12; + + private final ArtifactFactory artifactFactory; + + private final RepositorySystem repositorySystem; + + private final Log log; + + private final MavenSession mavenSession; + + private final List remotePluginRepositories; + + private final List remoteProjectRepositories; + + public DefaultResolverAdapter( + ArtifactFactory artifactFactory, RepositorySystem repositorySystem, Log log, MavenSession mavenSession) { + this.artifactFactory = artifactFactory; + this.repositorySystem = repositorySystem; + this.log = log; + this.mavenSession = mavenSession; + + this.remoteProjectRepositories = of(mavenSession) + .map(MavenSession::getCurrentProject) + .map(MavenProject::getRemoteProjectRepositories) + .map(this::forceDailyRemoteRepositoriesRefreshPolicy) + .orElseGet(Collections::emptyList); + + this.remotePluginRepositories = of(mavenSession) + .map(MavenSession::getCurrentProject) + .map(MavenProject::getRemotePluginRepositories) + .map(this::forceDailyRemoteRepositoriesRefreshPolicy) + .orElseGet(Collections::emptyList); + } + + private List forceDailyRemoteRepositoriesRefreshPolicy( + List remoteRepositories) { + return remoteRepositories.stream() + .map(remoteRepository -> { + RepositoryPolicy snapshotPolicy = forceDailyUpdatePolicy(remoteRepository.getPolicy(true)); + RepositoryPolicy releasePolicy = forceDailyUpdatePolicy(remoteRepository.getPolicy(false)); + if (snapshotPolicy != null || releasePolicy != null) { + RemoteRepository.Builder builder = new RemoteRepository.Builder(remoteRepository); + Optional.ofNullable(snapshotPolicy).ifPresent(builder::setSnapshotPolicy); + Optional.ofNullable(releasePolicy).ifPresent(builder::setReleasePolicy); + return builder.build(); + } else { + return remoteRepository; + } + }) + .collect(Collectors.toList()); + } + + private RepositoryPolicy forceDailyUpdatePolicy(RepositoryPolicy policy) { + if (policy.isEnabled() && RepositoryPolicy.UPDATE_POLICY_NEVER.equals(policy.getUpdatePolicy())) { + return new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, policy.getChecksumPolicy()); + } + return null; + } + + @Override + public void resolveArtifact(Artifact artifact, boolean usePluginRepositories) throws ArtifactResolutionException { + try { + ArtifactResult artifactResult = repositorySystem.resolveArtifact( + mavenSession.getRepositorySession(), + new ArtifactRequest( + RepositoryUtils.toArtifact(artifact), + usePluginRepositories + ? mavenSession.getCurrentProject().getRemotePluginRepositories() + : mavenSession.getCurrentProject().getRemoteProjectRepositories(), + getClass().getName())); + artifact.setFile(artifactResult.getArtifact().getFile()); + artifact.setVersion(artifactResult.getArtifact().getVersion()); + artifact.setResolved(artifactResult.isResolved()); + } catch (org.eclipse.aether.resolution.ArtifactResolutionException e) { + throw new ArtifactResolutionException(e.getMessage(), artifact, e); + } + } + + @Override + public ArtifactVersions resolveArtifactVersions( + Artifact artifact, boolean usePluginRepositories, boolean useProjectRepositories) + throws VersionRetrievalException { + try { + VersionRangeRequest versionRangeRequest = new VersionRangeRequest( + toArtifact(artifact).setVersion("(,)"), + Stream.concat( + usePluginRepositories ? remotePluginRepositories.stream() : Stream.empty(), + useProjectRepositories ? remoteProjectRepositories.stream() : Stream.empty()) + .distinct() + .collect(Collectors.toList()), + "lookupArtifactVersions"); + + return new ArtifactVersions( + artifact, + repositorySystem + .resolveVersionRange(mavenSession.getRepositorySession(), versionRangeRequest) + .getVersions() + .stream() + .map(v -> ArtifactVersionService.getArtifactVersion(v.toString())) + .collect(Collectors.toList())); + } catch (VersionRangeResolutionException e) { + throw new VersionRetrievalException(e.getMessage(), artifact, e); + } catch (RuntimeException e) { + // log the dependency should any runtime exception occur (e.x. broken comparison contract) + throw new VersionRetrievalException("Unable to retrieve versions for " + artifact, artifact, e); + } + } + + @Override + public SortedMap resolveDependencyVersions( + Collection dependencies, boolean usePluginRepositories, boolean useProjectRepositories) + throws VersionRetrievalException { + @SuppressWarnings("resource") + ExecutorService executor = Executors.newFixedThreadPool(LOOKUP_PARALLEL_THREADS); + try { + Collection>> futures = dependencies.stream() + .map(d -> Pair.of( + d, + executor.submit(() -> resolveArtifactVersions( + artifactFactory.createArtifact(d), usePluginRepositories, useProjectRepositories)))) + .collect(Collectors.toList()); + SortedMap result = new TreeMap<>(DependencyComparator.INSTANCE); + for (Pair> entry : futures) { + try { + result.put(entry.getKey(), entry.getValue().get()); + } catch (InterruptedException | ExecutionException e) { + if (e.getCause() instanceof VersionRetrievalException) { + throw (VersionRetrievalException) e.getCause(); + } + throw new VersionRetrievalException( + "Unable to resolve metadata for dependencies " + dependencies + ": " + e.getMessage(), + null, + e); + } + } + return result; + } finally { + executor.shutdown(); + } + } + + @Override + public PluginUpdatesDetails resolvePluginVersions(Plugin plugin) throws VersionRetrievalException { + String version = plugin.getVersion() != null ? plugin.getVersion() : "LATEST"; + Set pluginDependencies = Optional.ofNullable(plugin.getDependencies()) + .map(d -> d.stream().collect(Collectors.toCollection(() -> + (Set) new TreeSet<>(DependencyComparator.INSTANCE)))) + .orElse(Collections.emptySet()); + SortedMap pluginDependencyDetails = + resolveDependencyVersions(pluginDependencies, false, true); + Artifact pluginArtifact = + artifactFactory.createMavenPluginArtifact(plugin.getGroupId(), plugin.getArtifactId(), version); + ArtifactVersions allVersions = resolveArtifactVersions(pluginArtifact, true, false); + return new PluginUpdatesDetails(allVersions, pluginDependencyDetails, true); + } + + @Override + public SortedMap resolvePluginVersions(Collection plugins) + throws VersionRetrievalException { + @SuppressWarnings("resource") + ExecutorService executor = Executors.newFixedThreadPool(LOOKUP_PARALLEL_THREADS); + try { + SortedMap pluginUpdates = new TreeMap<>(PluginComparator.INSTANCE); + List>> futures = plugins.stream() + .map(p -> executor.submit(() -> new ImmutablePair<>(p, resolvePluginVersions(p)))) + .collect(Collectors.toList()); + for (Future> details : futures) { + Pair pair = details.get(); + pluginUpdates.put(pair.getKey(), pair.getValue()); + } + return pluginUpdates; + } catch (ExecutionException | InterruptedException e) { + if (e.getCause() instanceof VersionRetrievalException) { + throw (VersionRetrievalException) e.getCause(); + } + throw new VersionRetrievalException( + "Unable to acquire metadata for plugins " + plugins + ": " + e.getMessage(), null, e); + } finally { + executor.shutdown(); + } + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java index 39a5ec2588..fb540bb434 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/AbstractVersionChanger.java @@ -24,8 +24,11 @@ import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; /** - * Created by IntelliJ IDEA. - * + * Abstract base class for {@link VersionChanger} implementations. + *

+ * This class provides common functionality and holds references to the Maven Model, a mutable XML stream reader for the POM file, + * and a logger for logging purposes. + *

* @author Stephen Connolly * @since 15-Sep-2010 15:59:46 */ diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java index 60b114dd5e..a0e12a9581 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultDependencyVersionChange.java @@ -34,6 +34,13 @@ public final class DefaultDependencyVersionChange implements DependencyVersionCh private final String newVersion; + /** + * Creates a new instance, providing groupId, artifactId of the dependency as well as the old and new versions. + * @param groupId groupId of the dependency + * @param artifactId artifactId of the dependency + * @param oldVersion old version + * @param newVersion new version + */ public DefaultDependencyVersionChange(String groupId, String artifactId, String oldVersion, String newVersion) { this.groupId = groupId; this.artifactId = artifactId; @@ -41,22 +48,39 @@ public DefaultDependencyVersionChange(String groupId, String artifactId, String this.newVersion = newVersion; } + /** + * Returns the groupId of the dependency + * @return groupId of the dependency + */ public String getGroupId() { return groupId; } + /** + * Returns the artifact of the dependency + * @return artifactId of the dependency + */ public String getArtifactId() { return artifactId; } + /** + * Returns the old version of the dependency + * @return old version of the dependency + */ public String getOldVersion() { return oldVersion; } + /** + * Returns the new version of the dependency + * @return new version of the dependency + */ public String getNewVersion() { return newVersion; } + @Override public boolean equals(Object o) { if (this == o) { return true; @@ -79,6 +103,7 @@ public boolean equals(Object o) { return Objects.equals(oldVersion, versionChange.oldVersion); } + @Override public int hashCode() { int result = groupId != null ? groupId.hashCode() : 0; result = 31 * result + (artifactId != null ? artifactId.hashCode() : 0); @@ -87,6 +112,7 @@ public int hashCode() { return result; } + @Override public String toString() { return "DefaultDependencyVersionChange(" + groupId + ':' + artifactId + ":" + oldVersion + "-->" + newVersion + ')'; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java index 1c75aff441..cfe676c2eb 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DefaultPropertyVersionChange.java @@ -33,24 +33,43 @@ public final class DefaultPropertyVersionChange implements PropertyVersionChange private final String newValue; + /** + * Creates a new instance, providing a property name, old and new values of the property. + * @param property property name + * @param oldValue old property value + * @param newValue new property value + */ public DefaultPropertyVersionChange(String property, String oldValue, String newValue) { this.property = property; this.oldValue = oldValue; this.newValue = newValue; } + /** + * Returns the property name + * @return property name + */ public String getProperty() { return property; } + /** + * Returns the old value of the property + * @return old property value + */ public String getOldValue() { return oldValue; } + /** + * Returns the new value of the property + * @return new property value + */ public String getNewValue() { return newValue; } + @Override public boolean equals(Object o) { if (this == o) { return true; @@ -70,6 +89,7 @@ public boolean equals(Object o) { return Objects.equals(newValue, versionChange.newValue); } + @Override public int hashCode() { int result = property != null ? property.hashCode() : 0; result = 7 * result + (oldValue != null ? oldValue.hashCode() : 0); @@ -77,6 +97,7 @@ public int hashCode() { return result; } + @Override public String toString() { return "DefaultPropertyVersionChange(" + property + ':' + oldValue + "-->" + newValue + ')'; } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java index 54479b29e4..9dfc0ef7e8 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/DependencyVersionChanger.java @@ -24,10 +24,13 @@ import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; /** - * Created by IntelliJ IDEA. - * + * A {@link VersionChanger} implementation that changes dependency versions. + *

+ * This class extends the {@link AbstractVersionChanger} and provides functionality to update + * dependency versions in a Maven POM file. It utilizes the {@link PomHelper} to set the new versions + * and logs the changes made. + *

* @author Stephen Connolly - * @since 15-Sep-2010 16:00:32 */ public class DependencyVersionChanger extends AbstractVersionChanger { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java index ba8ee48845..ef9b436280 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/ParentVersionChanger.java @@ -24,7 +24,13 @@ import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; /** - * Version changer for the parent + * A {@link VersionChanger} implementation that changes dependency versions. + *

+ * This class extends the {@link AbstractVersionChanger} and provides functionality to update + * dependency versions in a Maven POM file. It utilizes the {@link PomHelper} to + * set the new versions and logs the changes made. + *

+ * @author Stephen Connolly */ public class ParentVersionChanger extends AbstractVersionChanger { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java index 6c57f9698c..f88b407d2f 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/PluginVersionChanger.java @@ -24,10 +24,13 @@ import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; /** - * Created by IntelliJ IDEA. - * + * A {@link VersionChanger} implementation that changes plugin versions. + *

+ * This class extends the {@link AbstractVersionChanger} and provides functionality to update + * plugin versions in a Maven POM file. It utilizes the {@link PomHelper} to + * set the new versions and logs the changes made. + *

* @author Stephen Connolly - * @since 15-Sep-2010 16:00:54 */ public class PluginVersionChanger extends AbstractVersionChanger { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java index 03a76eab78..8b56baa9bf 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/ProjectVersionChanger.java @@ -24,10 +24,13 @@ import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; /** - * Created by IntelliJ IDEA. - * + * A {@link VersionChanger} implementation that changes dependency versions. + *

+ * This class extends the {@link AbstractVersionChanger} and provides functionality to update + * dependency versions in a Maven POM file. It utilizes the {@link PomHelper} to + * set the new versions and logs the changes made. + *

* @author Stephen Connolly - * @since 15-Sep-2010 16:00:17 */ public class ProjectVersionChanger extends AbstractVersionChanger { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java index 75c7799b97..f0be12a621 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChanger.java @@ -20,7 +20,9 @@ import org.codehaus.mojo.versions.api.change.DependencyVersionChange; /** - * An abstract version changer, capable of changing versions of a given dependency. + * Describes an operation that can change the version of a dependency in a POM. + * + * @author Stephen Connolly */ public interface VersionChanger { /** diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java b/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java index 739fccc827..121d6d30b8 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/change/VersionChangerFactory.java @@ -27,38 +27,79 @@ import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; /** - * Created by IntelliJ IDEA. + * Factory for creating {@link VersionChanger} instances. + * + *

This factory must be initialized with a Maven {@link Model}, a mutable POM reader + * {@link MutableXMLStreamReader} and a {@link Log} before creating changers.

* * @author Stephen Connolly * @since 15-Sep-2010 16:05:27 */ public class VersionChangerFactory { + + /** + * Public no-arg constructor to provide an explicit constructor comment for Javadoc. + */ + public VersionChangerFactory() { + // no-op constructor + } + private Model model = null; private MutableXMLStreamReader pom = null; private Log log = null; + /** + * Returns the Maven model currently set on this factory. + * + * @return the configured {@link Model}, never {@code null} after proper initialization + */ public synchronized Model getModel() { return model; } + /** + * Sets the Maven model to be used by changers produced by this factory. + * + * @param model the {@link Model} to set; must not be {@code null} + */ public synchronized void setModel(Model model) { this.model = model; } + /** + * Returns the mutable POM XML reader currently set on this factory. + * + * @return the configured {@link MutableXMLStreamReader} + */ public synchronized MutableXMLStreamReader getPom() { return pom; } + /** + * Sets the mutable POM XML reader to be used by changers produced by this factory. + * + * @param pom the {@link MutableXMLStreamReader} to set; must not be {@code null} + */ public synchronized void setPom(MutableXMLStreamReader pom) { this.pom = pom; } + /** + * Returns the logger currently set on this factory. + * + * @return the configured {@link Log} + */ public synchronized Log getLog() { return log; } + /** + * Sets the logger to be used by changers produced by this factory. + * + * @param log the {@link Log} to set; must not be {@code null} + */ public synchronized void setLog(Log log) { this.log = log; } @@ -75,26 +116,57 @@ private synchronized void checkState() { } } + /** + * Creates a {@link PluginVersionChanger} configured with the factory's state. + * + * @return a new {@link PluginVersionChanger} + * @throws IllegalStateException if the factory has not been fully initialized + */ public synchronized VersionChanger newPluginVersionChanger() { checkState(); return new PluginVersionChanger(model, pom, log); } + /** + * Creates a {@link DependencyVersionChanger} configured with the factory's state. + * + * @return a new {@link DependencyVersionChanger} + * @throws IllegalStateException if the factory has not been fully initialized + */ public synchronized VersionChanger newDependencyVersionChanger() { checkState(); return new DependencyVersionChanger(model, pom, log); } + /** + * Creates a {@link ProjectVersionChanger} configured with the factory's state. + * + * @return a new {@link ProjectVersionChanger} + * @throws IllegalStateException if the factory has not been fully initialized + */ public synchronized VersionChanger newProjectVersionChanger() { checkState(); return new ProjectVersionChanger(model, pom, log); } + /** + * Creates a {@link ParentVersionChanger} configured with the factory's state. + * + * @return a new {@link ParentVersionChanger} + * @throws IllegalStateException if the factory has not been fully initialized + */ public synchronized VersionChanger newParentVersionChanger() { checkState(); return new ParentVersionChanger(model, pom, log); } + /** + * Creates a composite {@link VersionChanger} that will process parent, project, dependencies and plugins + * (in that order) using the factory's state. + * + * @return a new {@link CompositeVersionChanger} + * @throws IllegalStateException if the factory has not been fully initialized + */ public synchronized VersionChanger newVersionChanger() { checkState(); VersionChanger[] delegates = new VersionChanger[] { @@ -106,6 +178,16 @@ public synchronized VersionChanger newVersionChanger() { return new CompositeVersionChanger(delegates); } + /** + * Creates a composite {@link VersionChanger} that includes only the requested processors. + * + * @param processParent if true include a {@link ParentVersionChanger} + * @param processProject if true include a {@link ProjectVersionChanger} + * @param processDependencies if true include a {@link DependencyVersionChanger} + * @param processPlugins if true include a {@link PluginVersionChanger} + * @return a new {@link CompositeVersionChanger} composed of the selected changers + * @throws IllegalStateException if the factory has not been fully initialized + */ public synchronized VersionChanger newVersionChanger( boolean processParent, boolean processProject, boolean processDependencies, boolean processPlugins) { checkState(); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java index d2808a0a76..0890858122 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/DependencyFilter.java @@ -26,6 +26,12 @@ import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.versions.utils.DependencyComparator; +/** + * Provides a dependency matcher based on the list of strings of + * {@code groupId[:artifactId[:version[:type[:classifier[:scope]]]]]} for matching dependencies. + * + * @see TokenizedMatcher + */ public class DependencyFilter { private final String pattern; @@ -36,6 +42,16 @@ public class DependencyFilter { this.matchers = matchers; } + /** + * Creates a new instance based on a list of {@code groupId[:artifactId[:version[:type[:classifier[:scope]]]]]} + * expressions representing dependencies to be matched. + * + * @param dependencies a list of {@code groupId[:artifactId[:version[:type[:classifier[:scope]]]]]} + * expressions representing dependencies to be matched + * @return a new instance of {@link DependencyFilter} + * + * @see TokenizedMatcher + */ public static DependencyFilter parseFrom(List dependencies) { List matchers = dependencies.stream().map(TokenizedMatcher::parse).collect(Collectors.toList()); @@ -54,22 +70,35 @@ public String toString() { return String.format("%s{%s}", getClass().getSimpleName(), pattern); } + /** + * Filters the provided collection of dependencies, providing only the dependencies matching the set of expressions + * provided to the {@link DependencyFilter} instance + * @param dependencies dependencies to be filtered + * @return filtered list of dependencies, retaining only the dependencies matching the filter + */ public Set retainingIn(Collection dependencies) { return filterBy(dependencies, this::matchersMatch); } + /** + * Filters the provided collection of dependencies, providing only the dependencies which do not match the set of expressions + * provided to the {@link DependencyFilter} instance + * @param dependencies dependencies to be filtered + * @return filtered list of dependencies, excluding the dependencies matching the filter + */ public Set removingFrom(Collection dependencies) { return filterBy(dependencies, not(this::matchersMatch)); } + /** + * Says whether the given dependency matches the set of matchers defined by the {@link DependencyFilter} instance + * @param dependency dependency to be matched + * @return {@code true} if the given dependency satisfies the list of dependencies to be matched against + */ public boolean matchersMatch(Dependency dependency) { return matchers.stream().anyMatch(m -> m.test(dependency)); } - public boolean matchersDontMatch(Dependency dependency) { - return !matchersMatch(dependency); - } - private TreeSet filterBy(Collection dependencies, Predicate predicate) { return dependencies.stream() .filter(predicate) diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java index f5c984af68..9328a7b1b2 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/NullAwareWildcardMatcher.java @@ -19,9 +19,21 @@ * under the License. */ +/** + * An extended version of the {@link WildcardMatcher} where an additional special keyword {@code null} + * will match tokens which are null. + */ public class NullAwareWildcardMatcher extends WildcardMatcher { + /** + * Null keyword + */ public static final String NULL_KEYWORD = "null"; + /** + * Creates a new instance of the given pattern + * + * @param pattern pattern to be matched against + */ public NullAwareWildcardMatcher(String pattern) { super(pattern); } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java index b5cae8f60e..1f2788f312 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/TokenizedMatcher.java @@ -8,13 +8,28 @@ import org.apache.maven.model.Dependency; +/** + * Predicate that matches a {@link Dependency} against a colon-separated pattern. + *

+ * Patterns are of the form {@code groupId:artifactId:version:type:classifier:scope} where + * individual tokens may use wildcards. Use {@link #parse(String)} to create an instance. + */ public class TokenizedMatcher implements Predicate { + /** + * The tokens that may be used in a pattern. + */ public enum Tokens { + /** Token representing the dependency groupId. */ GROUP_ID(Dependency::getGroupId), + /** Token representing the dependency artifactId. */ ARTIFACT_ID(Dependency::getArtifactId), + /** Token representing the dependency version. */ VERSION(Dependency::getVersion), + /** Token representing the dependency type. */ TYPE(Dependency::getType), + /** Token representing the dependency classifier. */ CLASSIFIER(Dependency::getClassifier), + /** Token representing the dependency scope. */ SCOPE(Dependency::getScope); private final Function tokenExtractor; @@ -23,6 +38,11 @@ public enum Tokens { this.tokenExtractor = tokenExtractor; } + /** + * Returns a function that extracts this token's value from a {@link Dependency}. + * + * @return function extracting the token string from a dependency + */ public Function getTokenExtractor() { return tokenExtractor; } @@ -30,6 +50,11 @@ public Function getTokenExtractor() { private final Map> matchers; + /** + * Create a new matcher from the provided token-specific predicates. + * + * @param matchers the map of token predicates + */ private TokenizedMatcher(Map> matchers) { this.matchers = matchers; } @@ -50,6 +75,12 @@ public boolean test(Dependency dependency) { return true; } + /** + * Parse a colon-separated pattern into a {@link TokenizedMatcher}. + * + * @param pattern the pattern to parse (may be {@code null}) + * @return a matcher for the provided pattern + */ public static TokenizedMatcher parse(String pattern) { EnumMap> matchers = new EnumMap<>(Tokens.class); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java index 964a56e20e..6fbfa33572 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/filtering/WildcardMatcher.java @@ -6,15 +6,36 @@ import org.apache.maven.artifact.versioning.VersionRange; import org.codehaus.mojo.versions.utils.ArtifactVersionService; +/** + * A simple "matcher" object providing a utility whether the given string matches a pattern consisting of + * strings containing the wildcard ({@code *}) character. Each occurrence of the wildcard can be expanded + * to match any string. + */ public class WildcardMatcher implements Predicate { + /** + * The wildcard character. + */ public static final String WILDCARD = "*"; private final String pattern; + /** + * Creates a new matcher for the given pattern. Each occurrence of the wildcard ({@code *}) can be expanded + * to match any string. + * + * @param pattern pattern to be matched against. + */ protected WildcardMatcher(String pattern) { this.pattern = pattern; } + /** + * Creates a new matcher for the given pattern. Each occurrence of the wildcard ({@code *}) can be expanded + * to match any string. + * + * @param pattern pattern to be matched against. + * @return a new instance satisfying the provided pattern + */ public static WildcardMatcher parse(String pattern) { return new WildcardMatcher(pattern); } @@ -68,6 +89,10 @@ private boolean isVersionIncludedInRange(final String version, final String rang } } + /** + * Returns the pattern to be matched against + * @return pattern + */ public String getPattern() { return pattern; } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounter.java b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounter.java index 0e2eee5379..a760caef67 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounter.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounter.java @@ -33,8 +33,11 @@ * Default implementation of the {@link SegmentCounter} interface, using Maven's version rules, i.e. 1.3.34 > 1.3.9 * but 1.3.4.3.2.34 < 1.3.4.3.2.9. */ -public class DefaultSegmentCounter implements SegmentCounter { - public static final SegmentCounter INSTANCE = new DefaultSegmentCounter(); +public enum DefaultSegmentCounter implements SegmentCounter { + /** + * Singleton instance of the class + */ + INSTANCE; private static final Pattern SNAPSHOT_PATTERN = Pattern.compile("(-((\\d{8}\\.\\d{6})-(\\d+))|(SNAPSHOT))$"); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/InvalidSegmentException.java b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/InvalidSegmentException.java index 2be0171684..abc61732fe 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/InvalidSegmentException.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/InvalidSegmentException.java @@ -23,21 +23,27 @@ import org.codehaus.mojo.versions.api.Segment; /** - * Represents an invalid segment being identified within a version. + * Exception thrown when an invalid {@link Segment} is referenced for a particular {@link ArtifactVersion}. + * + *

The constructor requires a non-{@code null} {@link Segment} and {@link ArtifactVersion} and a non-negative + * segment count.

*/ public class InvalidSegmentException extends Exception { + /** The invalid segment identified. */ private final Segment segment; + /** The number of segments in the version under consideration. */ private final int segmentCount; + /** The ArtifactVersion being processed. */ private final ArtifactVersion version; /** - * Constructs the exception object + * Constructs a new {@code InvalidSegmentException}. * - * @param segment the invalid segment index. - * @param segmentCount the number of segments. - * @param version the version object. + * @param segment the invalid {@link Segment}; must not be {@code null} + * @param segmentCount the number of segments in the version; must be non-negative + * @param version the {@link ArtifactVersion} instance; must not be {@code null} */ public InvalidSegmentException(Segment segment, int segmentCount, ArtifactVersion version) { super(String.format( @@ -49,21 +55,27 @@ public InvalidSegmentException(Segment segment, int segmentCount, ArtifactVersio } /** - * @return segment + * Returns the invalid {@link Segment}. + * + * @return the invalid {@link Segment}; never {@code null} for a correctly constructed exception */ public Segment getSegment() { return segment; } /** - * @return segment count + * Returns the number of segments in the version. + * + * @return the segment count (non-negative) */ public int getSegmentCount() { return segmentCount; } /** - * @return version object + * Returns the {@link ArtifactVersion} associated with the exception. + * + * @return the {@link ArtifactVersion}; never {@code null} for a correctly constructed exception */ public ArtifactVersion getVersion() { return version; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/ReactorDepthComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/ReactorDepthComparator.java index fd51a65cce..168621f232 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/ReactorDepthComparator.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/ordering/ReactorDepthComparator.java @@ -27,7 +27,11 @@ import org.codehaus.mojo.versions.api.PomHelper; /** - * Compares project paths relative to the base directory based on their depth in a reactor + * Compares project paths relative to the base directory based on their depth in a reactor. + *

+ * The comparator uses the reactor {@link Model} instances to determine the number of + * parent levels for each project and orders shallower projects before deeper ones. If + * two projects have the same depth the result falls back to comparing their GAV strings. * * @author Stephen Connolly * @since 15-Sep-2010 14:54:42 @@ -35,10 +39,23 @@ public class ReactorDepthComparator implements Comparator { private final Map reactor; + /** + * Creates a new comparator using the given reactor map. + * + * @param reactor map of project base directories to their Maven {@link Model} instances; must not be {@code null} + */ public ReactorDepthComparator(Map reactor) { this.reactor = reactor; } + /** + * Compare two project base directories by their reactor depth, then by their GAV. + * + * @param o1 the first project base directory to compare + * @param o2 the second project base directory to compare + * @return negative if {@code o1} is ordered before {@code o2}, positive if after, zero if equal + */ + @Override public int compare(File o1, File o2) { final Model m1 = reactor.get(o1); final Model m2 = reactor.get(o2); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java index e3f74ac42e..07f48fad85 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultDependencyChangeRecord.java @@ -23,6 +23,12 @@ import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; import org.codehaus.mojo.versions.change.DefaultDependencyVersionChange; +/** + * Represents a change record of a dependency version. + * + * @author Slawomir Jaranowski + * @since 2.14.0 + */ public class DefaultDependencyChangeRecord implements DependencyChangeRecord { private final ChangeKind kind; private final DependencyVersionChange versionChange; @@ -42,6 +48,10 @@ public DependencyVersionChange getVersionChange() { return versionChange; } + /** + * Returns a new {@link Builder} instance. + * @return a new {@link Builder} instance + */ public static Builder builder() { return new Builder(); } @@ -56,6 +66,8 @@ public static class Builder { private String oldVersion; private String newVersion; + private Builder() {} + /** * Supplies the kind * @param kind requested kind diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java index 4b8eae61f7..11fabf9b37 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/recording/DefaultPropertyChangeRecord.java @@ -22,6 +22,12 @@ import org.codehaus.mojo.versions.api.recording.PropertyChangeRecord; import org.codehaus.mojo.versions.change.DefaultPropertyVersionChange; +/** + * Represents a change record of a property version. + * + * @author Slawomir Jaranowski + * @since 2.14.0 + */ public class DefaultPropertyChangeRecord implements PropertyChangeRecord { private final PropertyVersionChange versionChange; @@ -34,30 +40,58 @@ public PropertyVersionChange getVersionChange() { return versionChange; } + /** + * Returns a new {@link DefaultPropertyChangeRecord.Builder} instance. + * @return a new {@link DefaultPropertyChangeRecord.Builder} instance + */ public static Builder builder() { return new Builder(); } + /** + * Creates a new {@link Builder} instance + */ public static class Builder { private String property; private String oldValue; private String newValue; + private Builder() {} + + /** + * Provides a property name + * @param property property name + * @return {@link Builder} instance + */ public Builder withProperty(String property) { this.property = property; return this; } + /** + * Provides the old value of the property + * @param oldValue old property value + * @return {@link Builder} instance + */ public Builder withOldValue(String oldValue) { this.oldValue = oldValue; return this; } + /** + * Provides the new value of the property + * @param newValue new property value + * @return {@link Builder} instance + */ public Builder withNewValue(String newValue) { this.newValue = newValue; return this; } + /** + * Builds a new {@link PropertyChangeRecord} instance, based on the values provided to the builder. + * @return new {@link PropertyChangeRecord} instance + */ public PropertyChangeRecord build() { return new DefaultPropertyChangeRecord(new DefaultPropertyVersionChange(property, oldValue, newValue)); } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/rewriting/MutableXMLStreamReader.java b/versions-common/src/main/java/org/codehaus/mojo/versions/rewriting/MutableXMLStreamReader.java index 84c1d2e411..60d39c19e4 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/rewriting/MutableXMLStreamReader.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/rewriting/MutableXMLStreamReader.java @@ -18,7 +18,6 @@ import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import javax.xml.transform.TransformerException; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -73,7 +72,7 @@ public class MutableXMLStreamReader extends StreamReader2Delegate implements Aut * @throws IOException thrown in case of an I/O problems * @throws XMLStreamException thrown if the file cannot be parsed */ - public MutableXMLStreamReader(Path path) throws IOException, XMLStreamException, TransformerException { + public MutableXMLStreamReader(Path path) throws IOException, XMLStreamException { this(Files.newInputStream(path), path); } @@ -85,8 +84,7 @@ public MutableXMLStreamReader(Path path) throws IOException, XMLStreamException, * @throws IOException thrown in case of an I/O problems * @throws XMLStreamException thrown if the file cannot be parsed */ - public MutableXMLStreamReader(InputStream inputStream, Path fileName) - throws IOException, XMLStreamException, TransformerException { + public MutableXMLStreamReader(InputStream inputStream, Path fileName) throws IOException, XMLStreamException { super(null); this.fileName = fileName; init(inputStream); @@ -320,7 +318,7 @@ public void clearMark(Object markNr) { marks.remove(markNr); } - private void init(InputStream inputStream) throws IOException, XMLStreamException, TransformerException { + private void init(InputStream inputStream) throws IOException, XMLStreamException { try (BufferedInputStream buf = new BufferedInputStream(inputStream)) { buf.mark(0x4000); diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RuleService.java b/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RuleService.java index c5e7da38be..a7726ce565 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RuleService.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RuleService.java @@ -17,6 +17,13 @@ import org.codehaus.mojo.versions.model.RuleSet; import org.codehaus.mojo.versions.utils.RegexUtils; +/** + * Service providing access to rules and ignore-version handling. + *

+ * The service is constructed with a {@link Log} and a {@link RuleSet} and offers + * methods to find the best-fitting {@link Rule} for a given artifact and to + * collect the ignored versions for an artifact. + */ public class RuleService { Log log; @@ -24,6 +31,12 @@ public class RuleService { private final RuleSet ruleSet; + /** + * Creates a new {@code RuleService}. + * + * @param log the Maven log to use; may be {@code null} + * @param ruleSet the rules to apply; may be {@code null} + */ public RuleService(Log log, RuleSet ruleSet) { this.log = log; this.ruleSet = ruleSet; @@ -34,7 +47,7 @@ public RuleService(Log log, RuleSet ruleSet) { * * @param groupId Group id of the artifact * @param artifactId Artifact id of the artifact - * @return Rule which best describes the given artifact + * @return rule which best describes the given artifact, or {@code null} if none */ public Rule getBestFitRule(String groupId, String artifactId) { String groupArtifactId = groupId + ':' + artifactId; @@ -93,8 +106,35 @@ public Rule getBestFitRule(String groupId, String artifactId) { /** * Returns a list of versions which should not be considered when looking for updates. * - * @param artifact The artifact - * @return List of ignored version + * @param groupId groupId of the artifact to evaluate + * @param artifactId artifactId of the artifact to evaluate + * @return list of ignored versions (never {@code null}) + */ + public List getIgnoredVersions(String groupId, String artifactId) { + Rule bestFitRule = getBestFitRule(groupId, artifactId); + return Stream.concat( + ruleSet.getIgnoreVersions().stream(), + Optional.ofNullable(bestFitRule) + .map(Rule::getIgnoreVersions) + .map(Collection::stream) + .orElse(Stream.empty())) + .filter(v -> { + if (!IgnoreVersionHelper.isValidType(v)) { + log.warn("The type attribute '" + v.getType() + "' for global ignoreVersion[" + + v + "] is not valid. Please use one of '" + IgnoreVersionHelper.VALID_TYPES + + "'."); + return false; + } + return true; + }) + .collect(Collectors.toList()); + } + + /** + * Returns a list of versions which should not be considered when looking for updates. + * + * @param artifact the artifact to evaluate + * @return list of ignored versions (never {@code null}) */ public List getIgnoredVersions(Artifact artifact) { Rule bestFitRule = getBestFitRule(artifact.getGroupId(), artifact.getArtifactId()); @@ -117,7 +157,9 @@ public List getIgnoredVersions(Artifact artifact) { } /** - * @return rule set + * Returns the configured {@link RuleSet}. + * + * @return the rule set; may be {@code null} */ public RuleSet getRuleSet() { return ruleSet; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RuleServiceUtils.java b/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RuleServiceUtils.java new file mode 100644 index 0000000000..582c8cf672 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RuleServiceUtils.java @@ -0,0 +1,51 @@ +package org.codehaus.mojo.versions.rule; + +import java.util.Collection; + +import org.apache.maven.plugin.logging.Log; +import org.codehaus.mojo.versions.api.ArtifactVersions; +import org.codehaus.mojo.versions.api.IgnoreVersionHelper; +import org.codehaus.mojo.versions.model.IgnoreVersion; + +/** + * Utility class for filtering artifact versions based on rules. + * + * @since 2.20.0 + */ +public class RuleServiceUtils { + + /** + * Filters the given {@link ArtifactVersions} by ignoring versions as specified by the {@link RuleService} for the + * given artifact. + * + * @param groupId groupId of the artifact for which to filter versions + * @param artifactId artifactId of the artifact for which to filter versions + * @param artifactVersions the {@link ArtifactVersions} to filter + * @param ruleService the {@link RuleService} to retrieve ignored versions from + * @param log the {@link Log} for debug output + * @return a new {@link ArtifactVersions} instance with ignored versions filtered out + * @since 2.20.0 + */ + public static ArtifactVersions filterByRuleService( + String groupId, String artifactId, ArtifactVersions artifactVersions, RuleService ruleService, Log log) { + Collection ignoredVersions; + ignoredVersions = ruleService.getIgnoredVersions(groupId, artifactId); + String artifactKey = groupId + ":" + artifactId; + if (!ignoredVersions.isEmpty() && log.isDebugEnabled()) { + log.debug("Found ignored versions: " + ignoredVersions + " for artifact " + artifactKey); + } + return new ArtifactVersions(artifactVersions) + .filter(version -> ignoredVersions.stream().noneMatch(i -> { + if (IgnoreVersionHelper.isVersionIgnored(version, i)) { + if (log.isDebugEnabled()) { + log.debug("Version " + version + " for artifact " + + artifactKey + + " found on ignore list: " + + i); + } + return true; + } + return false; + })); + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RulesServiceBuilder.java b/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RulesServiceBuilder.java index 5586a7d1a5..aa0e360b7c 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RulesServiceBuilder.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/rule/RulesServiceBuilder.java @@ -33,9 +33,26 @@ import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.isBlank; +/** + * Builder for creating a {@link RuleService} instance. + *

+ * The builder allows configuring the source of rules (inline {@link org.codehaus.mojo.versions.model.RuleSet}, + * a URI, or a classpath resource), the server id for remote access, ignored versions and other + * optional runtime elements such as the {@link Log} and {@link MavenSession}. + */ public class RulesServiceBuilder { private static final String CLASSPATH_PROTOCOL = "classpath"; + /** + * Creates a new {@code RulesServiceBuilder}. + * + *

Provided to ensure the generated Javadoc documents the constructor rather than + * relying on the default constructor which triggers a javadoc warning.

+ */ + public RulesServiceBuilder() { + // no-op + } + private Collection ignoredVersions; private RuleSet ruleSet; private String serverId; @@ -45,41 +62,89 @@ public class RulesServiceBuilder { private Map wagonMap; + /** + * Configure an additional collection of ignored versions to be merged into the resulting rules. + * + * @param ignoredVersions collection of ignored version patterns + * @return this builder + */ public RulesServiceBuilder withIgnoredVersions(Collection ignoredVersions) { this.ignoredVersions = ignoredVersions; return this; } + /** + * Configure a {@link RuleSet} to be used directly (takes precedence over {@code rulesUri}). + * + * @param ruleSet the rule set to use + * @return this builder + */ public RulesServiceBuilder withRuleSet(RuleSet ruleSet) { this.ruleSet = ruleSet; return this; } + /** + * Configure the server id to use when creating remote repository access. + * + * @param serverId the server id + * @return this builder + */ public RulesServiceBuilder withServerId(String serverId) { this.serverId = serverId; return this; } + /** + * Configure a URI that points to an external rules XML document. Can be a classpath resource + * (prefix {@code classpath:}) or a remote URI handled via Wagon. + * + * @param rulesUri the rules URI + * @return this builder + */ public RulesServiceBuilder withRulesUri(String rulesUri) { this.rulesUri = rulesUri; return this; } + /** + * Configure the Maven {@link Log} to be used by the built {@link RuleService}. + * + * @param log the logging instance + * @return this builder + */ public RulesServiceBuilder withLog(Log log) { this.log = log; return this; } + /** + * Configure the current {@link MavenSession} used to resolve authentication and proxy information. + * + * @param mavenSession the maven session + * @return this builder + */ public RulesServiceBuilder withMavenSession(MavenSession mavenSession) { this.mavenSession = mavenSession; return this; } + /** + * Configure a map of Wagon implementations keyed by protocol. + * + * @param wagonMap map of protocol to {@link Wagon} + * @return this builder + */ public RulesServiceBuilder withWagonMap(Map wagonMap) { this.wagonMap = wagonMap; return this; } + /** + * Creates a new {@link RuleService} instance using the configured inputs. + * @return a new {@link RuleService} instance + * @throws MojoExecutionException if rules cannot be loaded from the configured URI + */ public RuleService build() throws MojoExecutionException { assert mavenSession != null; assert log != null; @@ -103,6 +168,19 @@ public RuleService build() throws MojoExecutionException { return new RuleService(log, ruleSet); } + /** + * Build the {@link RuleService} using the configured inputs. + * + * This method will load rules from the configured {@code ruleSet} if present, + * otherwise from the configured {@code rulesUri} (classpath or remote). If + * {@code ignoredVersions} are provided they will be merged into the resulting + * {@link org.codehaus.mojo.versions.model.RuleSet}. + * + * @return a new {@link RuleService} instance + * @throws MojoExecutionException if rules cannot be loaded from the configured URI + */ + // document the constructor warning in javadoc generation + private static class RulesUri { String basePath; String resource; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactFactory.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactFactory.java index 8c56fd0fe6..fea635ee57 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactFactory.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactFactory.java @@ -13,6 +13,9 @@ import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.model.Dependency; +/** + * Factory for creating {@link Artifact} instances. + */ @Named public class ArtifactFactory { private final ArtifactHandlerManager artifactHandlerManager; @@ -27,7 +30,18 @@ public ArtifactFactory(ArtifactHandlerManager artifactHandlerManager) { } /** - * Creates a new {@link Artifact} instance + * Creates a new {@link Artifact} instance with the given parameters. + * The version parameter may be a version range. + * @param groupId the groupId + * @param artifactId the artifactId + * @param version the version or version range + * @param type the type + * @param classifier the classifier + * @param scope the scope + * @param optional whether the dependency is optional + * @return the created {@link Artifact} instance + * @throws RuntimeException if the version parameter is not a valid version or version range + * (in this case the cause will be an {@link InvalidVersionSpecificationException}) */ public Artifact createArtifact( String groupId, @@ -54,7 +68,11 @@ public Artifact createArtifact( } /** - * Creates a new "maven-plugin"-type artifact + * Creates a new "maven-plugin"-type artifact with the given coordinates. The scope will be {@code runtime}. + * @param groupId the groupId + * @param artifactId the artifactId + * @param version the version + * @return the created {@link Artifact} instance */ public Artifact createMavenPluginArtifact(String groupId, String artifactId, String version) { return createArtifact(groupId, artifactId, version, "maven-plugin", null, "runtime", false); @@ -62,6 +80,8 @@ public Artifact createMavenPluginArtifact(String groupId, String artifactId, Str /** * Creates an {@link Artifact} object based on a {@link Dependency} instance + * @param dependency the dependency + * @return the created {@link Artifact} instance */ public Artifact createArtifact(Dependency dependency) { Artifact artifact = createArtifact( diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactVersionService.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactVersionService.java index 73303ca60a..44d36469dd 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactVersionService.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ArtifactVersionService.java @@ -33,8 +33,16 @@ public class ArtifactVersionService { private static final Map CACHE = new LRUMap<>(MAX_CACHE_SIZE); private static final ReentrantReadWriteLock CACHE_LOCK = new ReentrantReadWriteLock(); + private ArtifactVersionService() { + // prevent instantiation + } + /** - * Get a ComparableVersion representing the version in a string. + * Get an {@link ArtifactVersion} instance for the given version string. Uses a cache to avoid + * re-parsing versions that have already been seen. + * + * @param version the version string + * @return the corresponding {@link ArtifactVersion} instance */ public static ArtifactVersion getArtifactVersion(String version) { try { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ContextualLog.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ContextualLog.java index 06d794ceac..e70a5c9def 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ContextualLog.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ContextualLog.java @@ -30,7 +30,15 @@ */ public interface ContextualLog extends Log { + /** + * Set the current context. This will be printed before any log messages. + * + * @param context the context (e.g. the artifact being processed) + */ void setContext(String context); + /** + * Clear the current context. + */ void clearContext(); } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DelegatingContextualLog.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DelegatingContextualLog.java index fad4d642bd..d67d8d83b1 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DelegatingContextualLog.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DelegatingContextualLog.java @@ -24,10 +24,21 @@ import org.apache.maven.plugin.logging.Log; /** - * Created by IntelliJ IDEA. + * A {@link ContextualLog} implementation that delegates to a given {@link Log}. + *

+ * This class provides a way to add contextual information to log messages by + * maintaining a current context. When a context is set, the first log message + * at each level (debug, info, warn, error) will be prefixed with the context. + * When the context is cleared, a blank line is logged at the highest level + * that was used during the context. + *

+ *

+ * This is useful for grouping log messages related to a specific operation or + * component, making it easier to identify and understand the context of log + * entries. + *

* * @author Stephen Connolly - * @since 15-Sep-2010 15:52:21 */ public class DelegatingContextualLog implements ContextualLog { private final Log delegate; @@ -42,6 +53,11 @@ public class DelegatingContextualLog implements ContextualLog { private boolean currentContextReportedError = false; + /** + * Creates a new {@link DelegatingContextualLog} instance. + * + * @param delegate the delegate log + */ public DelegatingContextualLog(Log delegate) { this.delegate = delegate; } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyBuilder.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyBuilder.java index 107d1cf38b..069f5b8c4d 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyBuilder.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyBuilder.java @@ -25,9 +25,21 @@ * Builder class for {@linkplain Dependency} */ public class DependencyBuilder { + /** + * Enum representing the location of the element in the POM + */ public enum Location { + /** + * groupId location + */ GROUP_ID("groupId"), + /** + * artifactId location + */ ARTIFACT_ID("artifactId"), + /** + * version location + */ VERSION("version"); private final String stringValue; @@ -134,6 +146,12 @@ public DependencyBuilder withOptional(boolean optional) { return this; } + /** + * Passes location of the element in the POM to the builder + * @param element element name + * @param location location instance + * @return builder instance + */ public DependencyBuilder withLocation(String element, InputLocation location) { this.inputLocationMap.put(element, location); return this; diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyComparator.java index 75001c96dd..07fafd757b 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyComparator.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/DependencyComparator.java @@ -31,6 +31,9 @@ * @since 1.0-alpha-1 */ public enum DependencyComparator implements Comparator { + /** + * The singleton instance. + */ INSTANCE; /** @@ -40,7 +43,6 @@ public enum DependencyComparator implements Comparator { * @see java.util.Comparator#compare(Object, Object) * @since 1.0-alpha-1 */ - @SuppressWarnings("checkstyle:InnerAssignment") public int compare(Dependency d1, Dependency d2) { return d1 == d2 ? 0 @@ -49,8 +51,7 @@ public int compare(Dependency d1, Dependency d2) { dep -> ofNullable(dep.getArtifactId()).orElse("")) .thenComparing( dep -> ofNullable(dep.getClassifier()).orElse("")) - .thenComparing( - dep -> ofNullable(dep.getVersion()).orElse(""))) + .thenComparing(Dependency::getVersion, VersionStringComparator.STRICT)) .compare(d1, d2); } } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ExtensionUtils.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ExtensionUtils.java index dc83257c59..ec5a7cbe50 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ExtensionUtils.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/ExtensionUtils.java @@ -47,6 +47,10 @@ * Utilities for reading and handling extensions. */ public final class ExtensionUtils { + private ExtensionUtils() { + // prevent instantiation + } + /** * Reads the core extensions configured for the given project * from the {@code ${project}/.mvn/extensions.xml} file. diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MavenProjectUtils.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MavenProjectUtils.java index c1c2893916..96e35bce2f 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MavenProjectUtils.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MavenProjectUtils.java @@ -28,6 +28,7 @@ import org.apache.maven.model.Build; import org.apache.maven.model.Dependency; import org.apache.maven.model.DependencyManagement; +import org.apache.maven.model.Model; import org.apache.maven.model.PluginManagement; import org.apache.maven.model.Profile; import org.apache.maven.plugin.logging.Log; @@ -36,7 +37,6 @@ import static java.util.Collections.emptyList; import static java.util.Optional.ofNullable; -import static org.apache.commons.lang3.StringUtils.startsWith; import static org.codehaus.mojo.versions.utils.DependencyBuilder.Location.ARTIFACT_ID; import static org.codehaus.mojo.versions.utils.DependencyBuilder.Location.VERSION; @@ -44,6 +44,11 @@ * Utility methods for extracting dependencies from a {@link org.apache.maven.project.MavenProject} */ public class MavenProjectUtils { + + private MavenProjectUtils() { + // prevent instantiation + } + /** * Retrieves dependencies from the plugins section * @@ -117,10 +122,21 @@ public static Set extractDependenciesFromDependencyManagement( .peek(dependency -> log.debug("dependency from pom: " + dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion() + ":" + dependency.getScope())) - .map(dependency -> dependency.getVersion() != null - ? interpolateVersion(dependency, project) - : getVersionFromParent(dependency, project, processDependencyManagementTransitive, log) - .orElse(dependency)) + .map( + dependency -> { // resolve version from model properties if necessary (e.g. + // "${mycomponent.myversion}" + return dependency.getVersion() != null + ? interpolateVersion(dependency.getVersion(), project) + .map(v -> { + Dependency result = dependency.clone(); + result.setVersion(v); + return result; + }) + .orElse(dependency) + : getVersionFromParent( + dependency, project, processDependencyManagementTransitive, log) + .orElse(dependency); + }) .collect(() -> new TreeSet<>(DependencyComparator.INSTANCE), Set::add, Set::addAll); } @@ -160,30 +176,27 @@ private static Optional getVersionFromParent( /** * Attempts to interpolate the version from model properties. * - * @param dependency the dependency + * @param versionString string value of the version to interpolate * @param project the maven project - * @return the dependency with interpolated property (as far as possible) - * @since 2.14.0 + * @return an {@link Optional} object containing the interpolated string or {@link Optional#empty()} if no + * interpolation could take place + * @since 2.19.1 */ - public static Dependency interpolateVersion(final Dependency dependency, final MavenProject project) { + public static Optional interpolateVersion(String versionString, final MavenProject project) { // resolve version from model properties if necessary (e.g. "${mycomponent.myversion}" - if (startsWith(dependency.getVersion(), "${")) { - return ofNullable(project.getOriginalModel() - .getProperties() - .getProperty(dependency - .getVersion() - .substring(2, dependency.getVersion().length() - 1))) - .map(v -> { - Dependency result = dependency.clone(); - result.setVersion(v); - return result; - }) - .orElse(dependency); + while (versionString != null && versionString.startsWith("${")) { + String propertyName = versionString.substring(2, versionString.length() - 1); + versionString = ofNullable(project.getOriginalModel()) + .map(Model::getProperties) + .map(p -> p.getProperty(propertyName)) + .orElse(null); } - return dependency; + return ofNullable(versionString); } /** + * Retrieves dependencies from the dependencies of the project as well as its immediate parent project. + * @param dependency {@link Dependency} instance * @return {@code true} if the version of the dependency is definned locally in the same project */ public static boolean dependencyVersionLocalToReactor(Dependency dependency) { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MiscUtils.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MiscUtils.java index 984794ed6a..7ef9e00372 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MiscUtils.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/MiscUtils.java @@ -9,6 +9,10 @@ * Miscellaneous utility class. */ public class MiscUtils { + private MiscUtils() { + // prevent instantiation + } + /** * Filters a given map leaving only elements fulfilling a predicate. Does not change the input map, * the filtered map is returned as output. @@ -25,6 +29,17 @@ public static Map filter(Map map, Function predic .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } + /** + * Filters a given map leaving only elements fulfilling a predicate. Does not change the input map, + * the filtered map is returned as output. + * + * @param map input map to be filtered + * @param predicate predicate for element comparison + * @param mergeFunction function to resolve collisions between values associated with the same key + * @param key type + * @param value type + * @return map such that every element comforms with the predicate + */ public static Map filter( Map map, Function predicate, BinaryOperator mergeFunction) { return map.entrySet().stream() diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PluginComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PluginComparator.java index 01219cb5ac..ee34392a27 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PluginComparator.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PluginComparator.java @@ -30,12 +30,33 @@ * @since 1.0-beta-1 */ public enum PluginComparator implements Comparator { + /** + * The singleton instance. + */ INSTANCE; private static boolean isPluginOrReportPlugin(Object o) { return o instanceof Plugin || o instanceof ReportPlugin; } + private static String getGroupId(Object o) { + return o instanceof Plugin + ? ((Plugin) o).getGroupId() + : o instanceof ReportPlugin ? ((ReportPlugin) o).getGroupId() : ""; + } + + private static String getArtifactId(Object o) { + return o instanceof Plugin + ? ((Plugin) o).getArtifactId() + : o instanceof ReportPlugin ? ((ReportPlugin) o).getArtifactId() : ""; + } + + private static String getVersion(Object o) { + return o instanceof Plugin + ? ((Plugin) o).getVersion() + : o instanceof ReportPlugin ? ((ReportPlugin) o).getVersion() : ""; + } + /** * Compares to {@link Plugin} or {@link ReportPlugin} instances. * @@ -51,27 +72,12 @@ public int compare(Object o1, Object o2) { "This comparator can only be used to compare Plugin and ReportPlugin instances"); } - String g1 = o1 instanceof Plugin ? ((Plugin) o1).getGroupId() : ((ReportPlugin) o1).getGroupId(); - String g2 = o2 instanceof Plugin ? ((Plugin) o2).getGroupId() : ((ReportPlugin) o2).getGroupId(); - - int r = g1.compareTo(g2); - if (r == 0) { - String a1 = o1 instanceof Plugin ? ((Plugin) o1).getArtifactId() : ((ReportPlugin) o1).getArtifactId(); - String a2 = o2 instanceof Plugin ? ((Plugin) o2).getArtifactId() : ((ReportPlugin) o2).getArtifactId(); - r = a1.compareTo(a2); - } - if (r == 0) { - String v1 = o1 instanceof Plugin ? ((Plugin) o1).getVersion() : ((ReportPlugin) o1).getVersion(); - String v2 = o2 instanceof Plugin ? ((Plugin) o2).getVersion() : ((ReportPlugin) o2).getVersion(); - if (v1 == null) { - // hope I got the +1/-1 the right way around - return v2 == null ? 0 : -1; - } - if (v2 == null) { - return 1; - } - r = v1.compareTo(v2); + if (o1 == o2) { + return 0; } - return r; + return Comparator.nullsLast(Comparator.comparing(PluginComparator::getGroupId) + .thenComparing(PluginComparator::getArtifactId) + .thenComparing(PluginComparator::getVersion, VersionStringComparator.STRICT)) + .compare(o1, o2); } } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReader.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReader.java index 0754b981bd..a68ecbb6da 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReader.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReader.java @@ -23,7 +23,6 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.stream.Collectors; @@ -40,12 +39,13 @@ public class PropertiesVersionsFileReader { */ private String propertiesCsv; - private Property[] propertiesConfig; + private List propertiesConfig; - private String propertyFilePath; + private final String propertyFilePath; /** * Creates an instance of the object with the given path to the property file + * * @param filePath path to the property file */ public PropertiesVersionsFileReader(String filePath) { @@ -54,28 +54,23 @@ public PropertiesVersionsFileReader(String filePath) { /** * Reads the property file + * * @throws IOException thrown if an I/O exception occurs during the read operation */ public void read() throws IOException { try (InputStream input = Files.newInputStream(Paths.get(propertyFilePath))) { - Properties prop = new Properties(); - // load a properties file prop.load(input); - prop.propertyNames(); - propertiesCsv = prop.keySet().stream().map(Object::toString).collect(Collectors.joining(",")); - - List propertiesConfigList = new ArrayList<>(); - prop.forEach((name, version) -> { - Property propertyConfig = new Property((String) name); - propertyConfig.setVersion((String) version); - propertiesConfigList.add(propertyConfig); - }); - - propertiesConfig = propertiesConfigList.toArray(new Property[0]); + propertiesConfig = prop.entrySet().stream() + .map(e -> new Property((String) e.getKey()) { + { + setVersion((String) e.getValue()); + } + }) + .collect(Collectors.toList()); } } @@ -91,7 +86,7 @@ public String getProperties() { * Returns the array of {@link Property} objects * @return array of properties */ - public Property[] getPropertiesConfig() { + public List getPropertiesConfig() { return propertiesConfig; } } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java index 14833f7e57..c798f61068 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/PropertyComparator.java @@ -21,7 +21,6 @@ import java.util.Comparator; -import org.apache.commons.lang3.StringUtils; import org.codehaus.mojo.versions.api.Property; /** @@ -30,6 +29,9 @@ * @since 1.0-beta-1 */ public enum PropertyComparator implements Comparator { + /** + * The singleton instance. + */ INSTANCE; /** @@ -41,17 +43,9 @@ public enum PropertyComparator implements Comparator { * @see java.util.Comparator#compare(Object, Object) * @since 1.0-beta-1 */ - @SuppressWarnings("checkstyle:InnerAssignment") public int compare(Property p1, Property p2) { - int r; - return p1 == p2 - ? 0 - : p1 == null - ? 1 - : p2 == null - ? -1 - : (r = StringUtils.compare(p1.getName(), p2.getName())) == 0 - ? StringUtils.compare(p1.getValue(), p2.getValue()) - : r; + return Comparator.nullsLast(Comparator.comparing(Property::getName) + .thenComparing(Property::getValue, VersionStringComparator.LENIENT)) + .compare(p1, p2); } } diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/RegexUtils.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/RegexUtils.java index 014996ee69..01cc8faae1 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/RegexUtils.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/RegexUtils.java @@ -90,6 +90,18 @@ public static String quote(String s) { return sb.toString(); } + /** + * Calculates a score for a wildcard rule. The score is calculated as follows: + *
    + *
  • each {@code ?} character adds 1 to the score
  • + *
  • each {@code *} character adds 1000 to the score
  • + *
+ * Thus rules with fewer wildcards will have a lower score, and rules with more specific wildcards (i.e. {@code ?}) + * will have a lower score than those with less specific wildcards (i.e. {@code *}). + * + * @param wildcardRule the wildcard rule, may be {@code null} + * @return the score + */ public static int getWildcardScore(String wildcardRule) { int score = 0; if (wildcardRule != null) { diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/SegmentUtils.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/SegmentUtils.java index 9c4c53f397..2ad15ffd3a 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/SegmentUtils.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/SegmentUtils.java @@ -34,6 +34,10 @@ * Utility class for manipulating with {@link Segment} objects */ public class SegmentUtils { + private SegmentUtils() { + // prevent instantiation + } + /** *

Based on the passed flags, determines which segment which is not to be changed.

* diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/VersionStringComparator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/VersionStringComparator.java new file mode 100644 index 0000000000..d52adc86f8 --- /dev/null +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/VersionStringComparator.java @@ -0,0 +1,58 @@ +package org.codehaus.mojo.versions.utils; + +import java.util.Comparator; + +import org.eclipse.aether.util.version.GenericVersionScheme; +import org.eclipse.aether.version.InvalidVersionSpecificationException; +import org.eclipse.aether.version.Version; +import org.eclipse.aether.version.VersionScheme; + +/** + * A comparator for version strings. Can be strict (throws IllegalArgumentException if a version string + * cannot be parsed) or lenient (treats unparseable version strings as "0"). + */ +public enum VersionStringComparator implements Comparator { + /** + * Strict comparator: throws IllegalArgumentException if a version string cannot be parsed. + */ + STRICT(false), + /** + * Lenient comparator: treats unparseable version strings as "0". + */ + LENIENT(true); + + private final boolean lenient; + + VersionStringComparator(boolean lenient) { + this.lenient = lenient; + } + + private static final VersionScheme VERSION_SCHEME; + + private static final Version NULL_VERSION; + + static { + VERSION_SCHEME = new GenericVersionScheme(); + try { + NULL_VERSION = VERSION_SCHEME.parseVersion("0"); + } catch (InvalidVersionSpecificationException e) { + throw new IllegalArgumentException(e); + } + } + + private Version extractVersion(String v) { + try { + return VERSION_SCHEME.parseVersion(v); + } catch (InvalidVersionSpecificationException e) { + if (lenient) { + return NULL_VERSION; + } + throw new IllegalArgumentException(e); + } + } + + @Override + public int compare(String s1, String s2) { + return Comparator.nullsLast(Comparator.comparing(this::extractVersion)).compare(s1, s2); + } +} diff --git a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/VersionsExpressionEvaluator.java b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/VersionsExpressionEvaluator.java index 22aa75d6cb..da3b0b94d3 100644 --- a/versions-common/src/main/java/org/codehaus/mojo/versions/utils/VersionsExpressionEvaluator.java +++ b/versions-common/src/main/java/org/codehaus/mojo/versions/utils/VersionsExpressionEvaluator.java @@ -25,12 +25,16 @@ import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; /** - * Created by IntelliJ IDEA. - * + * An expression evaluator that can resolve plugin parameters as well as standard expressions. * @author Stephen Connolly - * @since 17-Mar-2009 08:51:42 */ public class VersionsExpressionEvaluator extends PluginParameterExpressionEvaluator implements ExpressionEvaluator { + /** + * Creates a new {@link VersionsExpressionEvaluator} instance. + * + * @param mavenSession the current maven session + * @param mojoExecution the current mojo execution + */ public VersionsExpressionEvaluator(MavenSession mavenSession, MojoExecution mojoExecution) { super(mavenSession, mojoExecution); } diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/api/AbstractVersionDetailsTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/api/AbstractVersionDetailsTest.java index 3bc5d73cf8..79467937b5 100644 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/api/AbstractVersionDetailsTest.java +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/api/AbstractVersionDetailsTest.java @@ -165,4 +165,50 @@ void testGetSelectedRestrictionForNoVersion() throws InvalidVersionSpecification instance.setCurrentVersionRange(VersionRange.createFromVersionSpec("[,0]")); assertThrows(NullPointerException.class, () -> instance.getSelectedRestriction(null)); } + + @Test + void testIsPreReleaseVersion() { + // Stable versions should not be pre-release + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0"), is(false)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("6.2.3"), is(false)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("6.2.4"), is(false)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("2.0.0"), is(false)); + + // Alpha versions + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-alpha"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-alpha1"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-alpha12"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-ALPHA"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-a"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-a1"), is(true)); + + // Beta versions + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-beta"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-beta1"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-BETA"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-b"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-b1"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("2.0.0-beta"), is(true)); + + // Milestone versions + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-M1"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-M2"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("7.0.0-M3"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-milestone"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-milestone1"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-m"), is(true)); + + // Release candidate versions + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-rc"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-rc1"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-RC"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-RC1"), is(true)); + + // Preview versions + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-preview"), is(true)); + assertThat(AbstractVersionDetails.isPreReleaseVersion("1.0.0-PREVIEW"), is(true)); + + // Null should return false + assertThat(AbstractVersionDetails.isPreReleaseVersion(null), is(false)); + } } diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java index 00deb3d737..044fb37bdc 100644 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/api/ArtifactVersionsTest.java @@ -20,15 +20,23 @@ */ import java.util.Arrays; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.Restriction; import org.apache.maven.artifact.versioning.VersionRange; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; +import org.codehaus.mojo.versions.utils.ArtifactVersionService; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import static java.util.Optional.of; import static org.codehaus.mojo.versions.api.Segment.INCREMENTAL; @@ -38,10 +46,14 @@ import static org.codehaus.mojo.versions.utils.ArtifactVersionUtils.version; import static org.codehaus.mojo.versions.utils.ArtifactVersionUtils.versions; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.emptyArray; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -272,4 +284,64 @@ void testGetNewestVersionWithLesserSegmentWithSnapshots() throws InvalidSegmentE instance.getNewestVersion("1.0.0", of(INCREMENTAL), true, false).get(), hasToString("1.0.0-1-SNAPSHOT")); } + + @ParameterizedTest + @ValueSource(strings = {"(1, 3]", "(0, 1], (2, 3]"}) + void testAllUpdatesWithCurrentVersionRange(String versionRange) throws InvalidVersionSpecificationException { + ArtifactVersions instance = new ArtifactVersions( + new DefaultArtifact( + "default-group", + "dummy-api", + VersionRange.createFromVersionSpec(versionRange), + "foo", + "bar", + "jar", + null), + Stream.of("1", "2", "3", "4") + .map(ArtifactVersionService::getArtifactVersion) + .collect(Collectors.toList())); + List allUpdates = Arrays.stream(instance.getAllUpdates(false)) + .map(Object::toString) + .collect(Collectors.toList()); + assertThat(allUpdates, hasItem("4")); + assertThat(allUpdates, allOf(not(hasItem("1")), not(hasItem("2")), not(hasItem("3")))); + } + + @Test + void testPredicate() { + ArtifactVersions original = new ArtifactVersions( + new DefaultArtifact("default-group", "dummy-api", "1.1.2-SNAPSHOT", "foo", "bar", "jar", null), + Arrays.asList(versions( + "1.0.1", + "1.0", + "1.1.0-2", + "1.1.1", + "1.1.1-2", + "1.1.2", + "1.1.2-SNAPSHOT", + "1.1.3", + "1.1", + "1.1-SNAPSHOT", + "1.2.1", + "1.2.2", + "1.2", + "1.3", + "1.9.1-SNAPSHOT", + "2.0", + "2.1.1-SNAPSHOT", + "2.1", + "3.0", + "3.1.1-SNAPSHOT", + "3.1.5-SNAPSHOT", + "3.4.0-SNAPSHOT"))); + ArtifactVersions onlySnapshots = new ArtifactVersions(original).filter(ArtifactUtils::isSnapshot); + assertThat(onlySnapshots.getVersions(false), emptyArray()); + assertThat(onlySnapshots.getVersions(true), arrayWithSize(7)); + assertThat(onlySnapshots.getCurrentVersion(), is(original.getCurrentVersion())); + + ArtifactVersions noSnapshots = new ArtifactVersions(original).filter(v -> !ArtifactUtils.isSnapshot(v)); + assertThat(noSnapshots.getVersions(false), arrayWithSize(15)); + assertThat(noSnapshots.getVersions(true), arrayWithSize(15)); + assertThat(noSnapshots.getCurrentVersion(), nullValue()); + } } diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java index cd406076da..eda8fc4cf4 100644 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java @@ -25,6 +25,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -179,7 +180,7 @@ void testMVERSIONS159ExcludedAndNotIncluded() throws Exception { VersionsHelper helper = createHelper(); MavenProject project = null; - Property[] propertyDefinitions = new Property[] {new Property("bar.version")}; + List propertyDefinitions = Collections.singletonList(new Property("bar.version")); // should not throw an IllegalStateException Map result = helper.getVersionPropertiesMap(VersionsHelper.VersionPropertiesMapRequest.builder() diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounterTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounterTest.java index 464d0eb450..7b859546c2 100644 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounterTest.java +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/ordering/DefaultSegmentCounterTest.java @@ -34,7 +34,7 @@ class DefaultSegmentCounterTest { @BeforeEach void beforeEach() { - this.instance = new DefaultSegmentCounter(); + this.instance = DefaultSegmentCounter.INSTANCE; } @Test diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/DependencyComparatorTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/DependencyComparatorTest.java new file mode 100644 index 0000000000..65b4faabd6 --- /dev/null +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/DependencyComparatorTest.java @@ -0,0 +1,131 @@ +package org.codehaus.mojo.versions.utils; + +import org.apache.maven.model.Dependency; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; + +class DependencyComparatorTest { + + private Dependency dep(String groupId, String artifactId, String version) { + return DependencyBuilder.newBuilder() + .withGroupId(groupId) + .withArtifactId(artifactId) + .withVersion(version) + .build(); + } + + @Test + void comparesByGroupIdThenArtifactIdThenVersion() { + Dependency a1 = dep("a.group", "artifact", "1.0"); + Dependency b1 = dep("b.group", "artifact", "1.0"); + + assertThat(DependencyComparator.INSTANCE.compare(a1, b1), lessThan(0)); + assertThat(DependencyComparator.INSTANCE.compare(b1, a1), greaterThan(0)); + } + + @Test + void comparesByArtifactIdWhenGroupIdEqual() { + Dependency a1 = dep("g", "a", "1.0"); + Dependency b1 = dep("g", "b", "1.0"); + + assertThat(DependencyComparator.INSTANCE.compare(a1, b1), lessThan(0)); + } + + @Test + void comparesByVersionWhenGroupAndArtifactEqual() { + Dependency v1 = dep("g", "a", "1.0"); + Dependency v2 = dep("g", "a", "2.0"); + + assertThat(DependencyComparator.INSTANCE.compare(v1, v2), lessThan(0)); + } + + @Test + void nullDependenciesAreHandled() { + Dependency d = dep("g", "a", "1.0"); + assertThat(DependencyComparator.INSTANCE.compare(null, d), greaterThan(0)); + assertThat(DependencyComparator.INSTANCE.compare(d, null), lessThan(0)); + assertThat(DependencyComparator.INSTANCE.compare(null, null), is(0)); + } + + @Test + void numericVersionsCompareSemanticallyNotLexicographically() { + Dependency v2 = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("2") + .build(); + Dependency v10 = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("10") + .build(); + + // Semantic: 2 < 10 + assertThat(DependencyComparator.INSTANCE.compare(v2, v10), lessThan(0)); + // Lexicographic would wrongly say "10" < "2" + } + + @Test + void patchVersionsCompareSemanticallyNotLexicographically() { + Dependency v102 = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("1.0.2") + .build(); + Dependency v1010 = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("1.0.10") + .build(); + + // Semantic: 1.0.2 < 1.0.10 + assertThat(DependencyComparator.INSTANCE.compare(v102, v1010), lessThan(0)); + // Lexicographic would wrongly say "1.0.10" < "1.0.2" + } + + @Test + void prereleaseIsLessThanRelease() { + Dependency alpha = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("1.0.0-alpha") + .build(); + Dependency release = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("1.0.0") + .build(); + + // Semantic: alpha < release + assertThat(DependencyComparator.INSTANCE.compare(alpha, release), lessThan(0)); + // Lexicographic would put "1.0.0-alpha" after "1.0.0" + } + + @Test + void versionsWithDifferentPrecisionAreEquivalent() { + Dependency v1 = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("1") + .build(); + Dependency v10 = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("1.0") + .build(); + Dependency v100 = DependencyBuilder.newBuilder() + .withGroupId("g") + .withArtifactId("a") + .withVersion("1.0.0") + .build(); + + // All should compare as equal + assertThat(DependencyComparator.INSTANCE.compare(v1, v10), is(0)); + assertThat(DependencyComparator.INSTANCE.compare(v10, v100), is(0)); + assertThat(DependencyComparator.INSTANCE.compare(v1, v100), is(0)); + } +} diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/MavenProjectUtilsTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/MavenProjectUtilsTest.java index e24c5da63c..ae7d397fdf 100644 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/MavenProjectUtilsTest.java +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/MavenProjectUtilsTest.java @@ -1,5 +1,6 @@ package org.codehaus.mojo.versions.utils; +import java.util.Optional; import java.util.Properties; import org.apache.maven.model.Dependency; @@ -7,11 +8,9 @@ import org.apache.maven.project.MavenProject; import org.junit.jupiter.api.Test; -import static org.codehaus.mojo.versions.utils.MavenProjectUtils.interpolateVersion; +import static java.util.Optional.empty; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.Matchers.sameInstance; import static org.hamcrest.core.Is.is; public class MavenProjectUtilsTest { @@ -36,12 +35,24 @@ public void testInterpolateVersion() { }); } }; - Dependency result = interpolateVersion(dep, proj); - assertThat(result.getVersion(), is("1.0.0")); + // resolve version from model properties if necessary (e.g. "${mycomponent.myversion}" + Optional result = MavenProjectUtils.interpolateVersion(dep.getVersion(), proj); + assertThat(result, is(Optional.of("1.0.0"))); } @Test - public void testImmutability() { + public void testInterpolateVersionNoChange() { + MavenProject proj = new MavenProject() { + { + setOriginalModel(new Model()); + } + }; + Optional result = MavenProjectUtils.interpolateVersion("${param}", proj); + assertThat(result.orElse(null), is(nullValue())); + } + + @Test + public void testInterpolateVersionDependencyNoChange() { Dependency dep = DependencyBuilder.newBuilder() .withGroupId("groupA") .withArtifactId("artifactA") @@ -49,40 +60,32 @@ public void testImmutability() { .build(); MavenProject proj = new MavenProject() { { - setOriginalModel(new Model() { - { - setProperties(new Properties() { - { - setProperty("param", "1.0.0"); - } - }); - } - }); + setOriginalModel(new Model()); } }; - assertThat(interpolateVersion(dep, proj), not(sameInstance(dep))); + // resolve version from model properties if necessary (e.g. "${mycomponent.myversion}" + Optional result = MavenProjectUtils.interpolateVersion(dep.getVersion(), proj); + assertThat(result, is(empty())); } @Test - public void testVersionlessDependency() { - Dependency dep = DependencyBuilder.newBuilder() - .withGroupId("groupA") - .withArtifactId("artifactA") - .build(); + public void testMultiLevelInterpolatedVersion() { MavenProject proj = new MavenProject() { { setOriginalModel(new Model() { { setProperties(new Properties() { { - setProperty("param", "1.0.0"); + setProperty("param1", "${param2}"); + setProperty("param2", "${param3}"); + setProperty("param3", "1.0.0"); } }); } }); } }; - Dependency result = interpolateVersion(dep, proj); - assertThat(result.getVersion(), nullValue()); + Optional result = MavenProjectUtils.interpolateVersion("${param1}", proj); + assertThat(result, is(Optional.of("1.0.0"))); } } diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PluginComparatorTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PluginComparatorTest.java new file mode 100644 index 0000000000..77bb53800f --- /dev/null +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PluginComparatorTest.java @@ -0,0 +1,117 @@ +package org.codehaus.mojo.versions.utils; + +import org.apache.maven.model.Plugin; +import org.apache.maven.model.ReportPlugin; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; + +class PluginComparatorTest { + + private Plugin plugin(String groupId, String artifactId, String version) { + Plugin p = new Plugin(); + p.setGroupId(groupId); + p.setArtifactId(artifactId); + p.setVersion(version); + return p; + } + + private ReportPlugin reportPlugin(String groupId, String artifactId, String version) { + ReportPlugin rp = new ReportPlugin(); + rp.setGroupId(groupId); + rp.setArtifactId(artifactId); + rp.setVersion(version); + return rp; + } + + @Test + void comparesByGroupIdThenArtifactIdThenVersion() { + Plugin a = plugin("a.group", "artifact", "1.0"); + Plugin b = plugin("b.group", "artifact", "1.0"); + + assertThat(PluginComparator.INSTANCE.compare(a, b), lessThan(0)); + assertThat(PluginComparator.INSTANCE.compare(b, a), greaterThan(0)); + } + + @Test + void comparesByArtifactIdWhenGroupIdEqual() { + Plugin a = plugin("g", "a", "1.0"); + Plugin b = plugin("g", "b", "1.0"); + + assertThat(PluginComparator.INSTANCE.compare(a, b), lessThan(0)); + } + + @Test + void comparesByVersionWhenGroupAndArtifactEqual() { + Plugin v1 = plugin("g", "a", "1.0"); + Plugin v2 = plugin("g", "a", "2.0"); + + assertThat(PluginComparator.INSTANCE.compare(v1, v2), lessThan(0)); + } + + @Test + void worksWithReportPluginAsWell() { + ReportPlugin rp1 = reportPlugin("g", "a", "1.0"); + ReportPlugin rp2 = reportPlugin("g", "a", "2.0"); + + assertThat(PluginComparator.INSTANCE.compare(rp1, rp2), lessThan(0)); + } + + @Test + void crossComparePluginAndReportPlugin() { + Plugin p = plugin("g", "a", "1.0"); + ReportPlugin rp = reportPlugin("g", "a", "2.0"); + + assertThat(PluginComparator.INSTANCE.compare(p, rp), lessThan(0)); + assertThat(PluginComparator.INSTANCE.compare(rp, p), greaterThan(0)); + } + + @Test + void semanticComparisonDiffersFromLexicographicNumeric() { + Plugin v2 = plugin("g", "a", "2"); + Plugin v10 = plugin("g", "a", "10"); + + // Semantic: 2 < 10 + assertThat(PluginComparator.INSTANCE.compare(v2, v10), lessThan(0)); + } + + @Test + void semanticComparisonDiffersFromLexicographicPatch() { + Plugin v102 = plugin("g", "a", "1.0.2"); + Plugin v1010 = plugin("g", "a", "1.0.10"); + + // Semantic: 1.0.2 < 1.0.10 + assertThat(PluginComparator.INSTANCE.compare(v102, v1010), lessThan(0)); + } + + @Test + void versionsWithDifferentPrecisionAreEquivalent() { + Plugin v1 = plugin("g", "a", "1"); + Plugin v10 = plugin("g", "a", "1.0"); + Plugin v100 = plugin("g", "a", "1.0.0"); + + assertThat(PluginComparator.INSTANCE.compare(v1, v10), is(0)); + assertThat(PluginComparator.INSTANCE.compare(v10, v100), is(0)); + assertThat(PluginComparator.INSTANCE.compare(v1, v100), is(0)); + } + + @Test + void prereleaseIsLessThanRelease() { + Plugin alpha = plugin("g", "a", "1.0.0-alpha"); + Plugin release = plugin("g", "a", "1.0.0"); + + assertThat(PluginComparator.INSTANCE.compare(alpha, release), lessThan(0)); + } + + @Test + void throwsOnNonPluginObjects() { + Object notAPlugin = new Object(); + Plugin p = plugin("g", "a", "1.0"); + + org.junit.jupiter.api.Assertions.assertThrows( + IllegalArgumentException.class, () -> PluginComparator.INSTANCE.compare(notAPlugin, p)); + } +} diff --git a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java index fc1e00d819..8c5a1f358e 100644 --- a/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java +++ b/versions-common/src/test/java/org/codehaus/mojo/versions/utils/PropertiesVersionsFileReaderTest.java @@ -43,7 +43,7 @@ void testRead() throws IOException { int numberOfPropertiesConfig = 3; assertTrue(equalsCvsUnordered( "booking-api.version,booking-lib.version,be-air-impl.version", reader.getProperties())); - assertEquals(numberOfPropertiesConfig, reader.getPropertiesConfig().length); + assertEquals(numberOfPropertiesConfig, reader.getPropertiesConfig().size()); } private boolean equalsCvsUnordered(String csvExpected, String csvActual) { diff --git a/versions-enforcer/pom.xml b/versions-enforcer/pom.xml index 88eff20025..888b9568b5 100644 --- a/versions-enforcer/pom.xml +++ b/versions-enforcer/pom.xml @@ -4,7 +4,7 @@ org.codehaus.mojo.versions versions - 2.19.1 + 2.20.1 versions-enforcer @@ -128,6 +128,20 @@ + + + + + maven-javadoc-plugin + + + -Werror + + + + + + + maven-javadoc-plugin + + all,-missing + + -quiet + + + diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/invoker.properties b/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/invoker.properties new file mode 100644 index 0000000000..fa969d852b --- /dev/null +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates +invoker.mavenOpts=-DprocessDependencyManagementTransitive=true diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/pom.xml b/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/pom.xml new file mode 100644 index 0000000000..d22ccbd936 --- /dev/null +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + localhost + it-display-dependency-updates-001 + 1.0 + pom + display-dependency-updates + http://localhost/ + + + localhost + dummy-api + + + + + + localhost + dummy-api-impl-bom-pom + 1.0 + pom + import + + + + + + + + localhost + dummy-maven-plugin + 1.0 + + + maven-clean-plugin + 2.2 + + + maven-deploy-plugin + 2.3 + + + maven-install-plugin + 2.2 + + + maven-site-plugin + 2.0 + + + maven-project-info-reports-plugin + 2.1 + + + + + diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/verify.groovy b/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/verify.groovy deleted file mode 100644 index 8db417fbf0..0000000000 --- a/versions-maven-plugin/src/it/it-display-dependency-updates-009-processDependencyManagementTransitive-true/verify.groovy +++ /dev/null @@ -1,4 +0,0 @@ -def buildLog = new File( basedir, "build.log").text -assert buildLog =~ /\Qlocalhost:dummy-api\E\s*\.*\s*1\.1\s+->\s+3\.0/ -assert buildLog =~ /\Qlocalhost:dummy-impl\E\s*\.*\s*1\.2\s+->\s+2\.2/ -assert !(buildLog =~ /\Qlocalhost:dummy-api-impl-bom-pom\E\s*\.*\s*1\.0\s+->\s+2\.0/) diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/invoker.properties b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/invoker.properties new file mode 100644 index 0000000000..7fc2578ce0 --- /dev/null +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals = ${project.groupId}:${project.artifactId}:${project.version}:display-dependency-updates +invoker.mavenOpts = -Dversions.outputFile=./output.txt -DoutputEncoding=UTF-8 \ No newline at end of file diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/pom.xml b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/pom.xml new file mode 100644 index 0000000000..8d092503df --- /dev/null +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + localhost + it-display-dependency-updates-issue-1295-version-ranges + 1.0 + pom + + + + localhost + dummy-api + [1.1,4.0) + + + + diff --git a/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/verify.groovy b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/verify.groovy new file mode 100644 index 0000000000..6dbb2805b2 --- /dev/null +++ b/versions-maven-plugin/src/it/it-display-dependency-updates-issue-1295-version-ranges/verify.groovy @@ -0,0 +1,2 @@ +def output = new File(basedir, "output.txt").text +assert output =~ /No dependencies in Dependencies have newer versions./ diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/bom/pom.xml b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/bom/pom.xml new file mode 100644 index 0000000000..dac7a5eb45 --- /dev/null +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/bom/pom.xml @@ -0,0 +1,24 @@ + + 4.0.0 + + + localhost + grandparent + 1.0 + + + bom + pom + + + + + localhost + library + 1.0 + + + + + diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/invoker.properties b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/invoker.properties new file mode 100644 index 0000000000..bdb73fc388 --- /dev/null +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/invoker.properties @@ -0,0 +1 @@ +invoker.goals=-X ${project.groupId}:${project.artifactId}:${project.version}:resolve-ranges diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/library/pom.xml b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/library/pom.xml new file mode 100644 index 0000000000..e836b581bb --- /dev/null +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/library/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + + localhost + grandparent + 1.0 + + + library + + + + test.package + moduleTest + 0.0.2.19 + + + + diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/parent/child/pom.xml b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/parent/child/pom.xml new file mode 100644 index 0000000000..abf0a8ed8c --- /dev/null +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/parent/child/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + + + localhost + parent + 1.0 + + + child + + + + localhost + library + + + + diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/parent/pom.xml b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/parent/pom.xml new file mode 100644 index 0000000000..b99f53ce61 --- /dev/null +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/parent/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + + + localhost + grandparent + 1.0 + + + parent + pom + + + child + + + + + + + test.package + moduleTest + + + + localhost + bom + 1.0 + pom + import + + + + + diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/pom.xml b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/pom.xml new file mode 100644 index 0000000000..df046c379f --- /dev/null +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/pom.xml @@ -0,0 +1,25 @@ + + 4.0.0 + + localhost + grandparent + 1.0 + pom + + + bom + parent + library + + + + + + test.package + moduleTest + 0.0.2.18 + + + + diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/verify.groovy b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/verify.groovy new file mode 100644 index 0000000000..12b672e3ff --- /dev/null +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-1287/verify.groovy @@ -0,0 +1,2 @@ +def buildLogFile = new File(basedir, "build.log") +assert buildLogFile.text.contains("Found managed dependency test.package:moduleTest:jar without a version") diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/invoker.properties b/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/invoker.properties index b4d5204b00..6f7b0250e4 100644 --- a/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/invoker.properties +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/invoker.properties @@ -1,2 +1,2 @@ invoker.goals=-X ${project.groupId}:${project.artifactId}:${project.version}:resolve-ranges -invoker.buildResult=failure +invoker.buildResult=success diff --git a/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/verify.groovy b/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/verify.groovy index fae229f113..f6a1614826 100644 --- a/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/verify.groovy +++ b/versions-maven-plugin/src/it/it-resolve-ranges-issue-442/verify.groovy @@ -1,2 +1,2 @@ def buildLogFile = new File(basedir, "build.log") -assert buildLogFile.text.contains("MojoExecutionException: Found invalid managed dependency junit:junit:jar without a version") \ No newline at end of file +assert buildLogFile.text.contains("Found managed dependency junit:junit:jar without a version") diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractDependencyUpdatesReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractDependencyUpdatesReport.java index afad34885a..fbeb19ab92 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractDependencyUpdatesReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractDependencyUpdatesReport.java @@ -52,6 +52,7 @@ /** * Generates a report of available updates for the dependencies of a project. + * Base class, abstracting functionality regardless of whether we're rendering an individual, or an aggregate report. */ public abstract class AbstractDependencyUpdatesReport extends AbstractVersionsReport { @@ -111,6 +112,15 @@ public abstract class AbstractDependencyUpdatesReport extends AbstractVersionsRe @Parameter(property = "onlyUpgradable", defaultValue = "false") protected boolean onlyUpgradable; + /** + * Creates a new instance. + * + * @param i18n {@link I18N} bean instance + * @param artifactFactory {@link ArtifactFactory} bean instance + * @param repositorySystem {@link RepositorySystem} bean instance + * @param wagonMap map of {@link Wagon} instances per protocol + * @param rendererFactory {@link ReportRendererFactory} instance + */ protected AbstractDependencyUpdatesReport( I18N i18n, ArtifactFactory artifactFactory, @@ -201,6 +211,14 @@ protected void doGenerateReport(Locale locale, Sink sink) throws MavenReportExce } } + /** + * Collects transitive dependency management, storing the dependencies in the provided collector + * + * @param project instance of {@link MavenProject} + * @param dependencyManagementCollector a mutable {@link Set} instance, which will be used to collect + * dependencies from the project + * @throws MavenReportException thrown if it's not possible to retrieve versions for any of the dependencies + */ protected void handleDependencyManagementTransitive( MavenProject project, Set dependencyManagementCollector) throws MavenReportException { try { @@ -227,8 +245,8 @@ private void handleOnlyProjectDependencies(Set dependencyManagement, * in projects direct dependencies section. * * @return a {@link Set} that can be additionally populated by {@link #populateDependencies(Set)}. - * If not, an empty set is returned - * */ + * If not, an empty set is returned + */ private Set getDependencies() { final Set dependenciesCollector = new TreeSet<>(DEPENDENCY_COMPARATOR); populateDependencies(dependenciesCollector); @@ -241,8 +259,8 @@ private Set getDependencies() { * in the creation of the report. * * @param dependenciesCollector, a Set, initialized with a DependencyComparator - * comparator. - * */ + * comparator. + */ protected abstract void populateDependencies(Set dependenciesCollector); /** @@ -251,8 +269,8 @@ private Set getDependencies() { * in projects dependencyManagement section. * * @return a {@link Set} that can be additionally populated by - * {@link #populateDependencyManagement(Set)}. If not, an empty set is returned - * */ + * {@link #populateDependencyManagement(Set)}. If not, an empty set is returned + */ private Set getDependencyManagement() throws MavenReportException { final Set dependencyManagementCollector = new TreeSet<>(DEPENDENCY_COMPARATOR); populateDependencyManagement(dependencyManagementCollector); @@ -265,10 +283,9 @@ private Set getDependencyManagement() throws MavenReportException { * in the creation of the report. * * @param dependencyManagementCollector, a Set initialized with a DependencyComparator - * comparator. - * + * comparator. * @throws MavenReportException when things go wrong. - * */ + */ protected abstract void populateDependencyManagement(Set dependencyManagementCollector) throws MavenReportException; @@ -308,6 +325,11 @@ private boolean match(Dependency dep, Dependency dmDep) { || dmDep.getVersion().equals(dep.getVersion())); } + /** + * Returns {@code true} if the given {@link MavenProject} has a non-empty dependency management section + * @param project {@link MavenProject} instance + * @return {@code true} if the given {@link MavenProject} has a non-empty dependency management section + */ protected boolean hasDependencyManagement(MavenProject project) { if (project == null) { return false; diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPluginUpdatesReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPluginUpdatesReport.java index f6f3807f42..f2452d8966 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPluginUpdatesReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPluginUpdatesReport.java @@ -47,6 +47,7 @@ /** * Generates a report of available updates for the plugins of a project. + * Base class, abstracting functionality regardless of whether we're rendering an individual, or an aggregate report. */ public abstract class AbstractPluginUpdatesReport extends AbstractVersionsReport { @@ -75,6 +76,15 @@ public abstract class AbstractPluginUpdatesReport extends AbstractVersionsReport @Parameter(property = "onlyUpgradable", defaultValue = "false") protected boolean onlyUpgradable; + /** + * Creates a new instance. + * + * @param i18n {@link I18N} bean instance + * @param artifactFactory {@link ArtifactFactory} bean instance + * @param repositorySystem {@link RepositorySystem} bean instance + * @param wagonMap map of {@link Wagon} instances per protocol + * @param rendererFactory {@link ReportRendererFactory} instance + */ protected AbstractPluginUpdatesReport( I18N i18n, ArtifactFactory artifactFactory, @@ -100,6 +110,11 @@ public boolean canGenerateReport() { return haveBuildPlugins(getProject()) || haveBuildPluginManagementPlugins(getProject()); } + /** + * Returns {@code true} if the given {@link MavenProject} has a non-empty plugin management section + * @param project {@link MavenProject} instance + * @return {@code true} if the given {@link MavenProject} has a non-empty plugin management section + */ protected boolean haveBuildPluginManagementPlugins(MavenProject project) { return project.getBuild() != null && project.getBuild().getPluginManagement() != null @@ -107,6 +122,11 @@ protected boolean haveBuildPluginManagementPlugins(MavenProject project) { && !project.getBuild().getPluginManagement().getPlugins().isEmpty(); } + /** + * Returns {@code true} if the given {@link MavenProject} has a non-empty plugins section. + * @param project {@link MavenProject} instance + * @return {@code true} if the given {@link MavenProject} has a non-empty plugins section. + */ protected boolean haveBuildPlugins(MavenProject project) { return project.getBuild() != null && project.getBuild().getPlugins() != null diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPropertyUpdatesReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPropertyUpdatesReport.java index 918795771e..9233d22032 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPropertyUpdatesReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractPropertyUpdatesReport.java @@ -21,6 +21,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TreeMap; @@ -33,7 +34,7 @@ import org.apache.maven.wagon.Wagon; import org.codehaus.mojo.versions.api.Property; import org.codehaus.mojo.versions.api.PropertyVersions; -import org.codehaus.mojo.versions.api.VersionsHelper.VersionPropertiesMapRequest; +import org.codehaus.mojo.versions.api.VersionsHelper; import org.codehaus.mojo.versions.reporting.ReportRendererFactory; import org.codehaus.mojo.versions.reporting.model.PropertyUpdatesModel; import org.codehaus.mojo.versions.utils.ArtifactFactory; @@ -45,6 +46,7 @@ /** * Generates a report of available updates for properties of a project which are linked to the dependencies and/or * plugins of a project. + * Base class, abstracting functionality regardless of whether we're rendering an individual, or an aggregate report. */ public abstract class AbstractPropertyUpdatesReport extends AbstractVersionsReport { @@ -56,7 +58,7 @@ public abstract class AbstractPropertyUpdatesReport extends AbstractVersionsRepo * @since 1.0-beta-1 */ @Parameter - private Property[] properties; + private List properties; /** * A comma separated list of properties to include in the report. @@ -98,6 +100,15 @@ public abstract class AbstractPropertyUpdatesReport extends AbstractVersionsRepo @Parameter(property = "propertyUpdatesReportFormats", defaultValue = "html") protected String[] formats = new String[] {"html"}; + /** + * Creates a new instance. + * + * @param i18n {@link I18N} bean instance + * @param artifactFactory {@link ArtifactFactory} bean instance + * @param repositorySystem {@link RepositorySystem} bean instance + * @param wagonMap map of {@link Wagon} instances per protocol + * @param rendererFactory {@link ReportRendererFactory} instance + */ protected AbstractPropertyUpdatesReport( I18N i18n, ArtifactFactory artifactFactory, @@ -123,11 +134,16 @@ public boolean canGenerateReport() { return haveBuildProperties(); } + /** + * Returns whether the current project has any properties defined in its build. + * @return {@code true} if the current project has properties, {@code false} otherwise + */ protected boolean haveBuildProperties() { return getProject().getProperties() != null && !getProject().getProperties().isEmpty(); } + @Override protected void doGenerateReport(Locale locale, Sink sink) throws MavenReportException { try { final Map updateSet = new TreeMap<>(PROPERTIES_COMPARATOR); @@ -173,12 +189,26 @@ private void renderReport(Locale locale, Sink sink, PropertyUpdatesModel propert } } - private PropertyUpdatesModel getPropertyUpdatesModel(Map updateSet) { - return new PropertyUpdatesModel(PROPERTIES_COMPARATOR, updateSet); + /** + * Returns an instance of the {@link PropertyUpdatesModel} given the retrieved map of updates per property. + * Does not mutate the map in the argument. + * @param updateMap populated map of updates per property + * @return generated model, based on the provided map of updates per property + */ + private PropertyUpdatesModel getPropertyUpdatesModel(Map updateMap) { + return new PropertyUpdatesModel(PROPERTIES_COMPARATOR, updateMap); } - protected VersionPropertiesMapRequest getRequest(MavenProject project) { - return VersionPropertiesMapRequest.builder() + /** + * Creates a new instance of the {@link VersionsHelper.VersionPropertiesMapRequest} based on the provided {@link MavenProject}. + * The created instance is built taking into consideration the provided project as well as parameters of the Mojo + * such as {@link #properties}, {@link #includeProperties}, {@link #excludeProperties}, {@link #includeParent}, + * {@link #autoLinkItems}. + * @param project {@link MavenProject} instance for which the request is to be generated + * @return an initialised {@link VersionsHelper.VersionPropertiesMapRequest} instance + */ + protected VersionsHelper.VersionPropertiesMapRequest getRequest(MavenProject project) { + return VersionsHelper.VersionPropertiesMapRequest.builder() .withMavenProject(project) .withPropertyDefinitions(this.properties) .withIncludeProperties(this.includeProperties) diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java index 49e79aaa17..ca93bf4aab 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java @@ -135,6 +135,14 @@ public abstract class AbstractVersionsDependencyUpdaterMojo extends AbstractVers @Parameter(property = "excludeReactor", defaultValue = "true") private boolean excludeReactor = true; + /** + * The reactor projects for the current build. + * @param artifactFactory {@link ArtifactFactory} bean instance + * @param repositorySystem {@link RepositorySystem} bean instance + * @param wagonMap a map of {@link Wagon} instances per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException thrown if an error occurs + */ @Inject protected AbstractVersionsDependencyUpdaterMojo( ArtifactFactory artifactFactory, @@ -219,6 +227,12 @@ protected Artifact toArtifact(Dependency dependency) throws MojoExecutionExcepti return findArtifact(dependency).orElse(artifactFactory.createArtifact(dependency)); } + /** + * Try to find the artifact that matches the given parent model. + * @param model Parent model + * @return Artifact for the parent + * @throws MojoExecutionException thrown if the dependency cannot be converted to an artifacted + */ protected Artifact toArtifact(Parent model) throws MojoExecutionException { return this.toArtifact(DependencyBuilder.newBuilder() .withGroupId(model.getGroupId()) @@ -242,6 +256,13 @@ protected Dependency getParentDependency() { .build(); } + /** + * Returns a string representation of the project in the form groupId:artifactId:version (omitting version if it is + * null or empty). + * + * @param project MavenProject + * @return String representation of the project + */ protected String toString(MavenProject project) { StringBuilder buf = new StringBuilder(); @@ -257,6 +278,13 @@ protected String toString(MavenProject project) { return buf.toString(); } + /** + * Returns a string representation of the dependency in the form groupId:artifactId:type:classifier:version + * (omitting type and classifier if they are null or empty, and omitting version if it is null or empty). + * + * @param d Dependency + * @return String representation of the dependency + */ protected String toString(Dependency d) { StringBuilder buf = new StringBuilder(); buf.append(d.getGroupId()); @@ -464,6 +492,7 @@ private int findFirstChar(final String includeString, final String chars) { * @param changeKind title for the {@link ChangeRecorder} log * @return {@code true} if an update has been made, {@code false} otherwise * @throws XMLStreamException thrown if updating the XML doesn't succeed + * @throws MojoExecutionException thrown if the dependency cannot be converted to an artifact */ protected boolean updateDependencyVersion( MutableXMLStreamReader pom, Dependency dep, String newVersion, DependencyChangeRecord.ChangeKind changeKind) diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java index d38bbc736e..d47a6ae732 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java @@ -62,6 +62,14 @@ public abstract class AbstractVersionsDisplayMojo extends AbstractVersionsUpdate @Parameter(property = "versions.outputFile") protected File outputFile; + /** + * If {@code true}, output file will be overwritten if it already exists + * + * @since 2.20 + */ + @Parameter(property = "versions.overwriteOutput", defaultValue = "false") + protected boolean overwriteOutput; + /** * Controls whether the display output is logged to the console. * @@ -90,6 +98,14 @@ public abstract class AbstractVersionsDisplayMojo extends AbstractVersionsUpdate private boolean outputFileError = false; + /** + * Creates a new instance. + * @param artifactFactory a {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of {@link Wagon} instances per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException thrown if an error occurs + */ @Inject protected AbstractVersionsDisplayMojo( ArtifactFactory artifactFactory, @@ -100,6 +116,9 @@ protected AbstractVersionsDisplayMojo( super(artifactFactory, repositorySystem, wagonMap, changeRecorders); } + /** + * Initialise logging to file if required. + */ @SuppressWarnings("unchecked") protected void logInit() { if (outputFile != null && !outputFileError) { @@ -118,7 +137,7 @@ protected void logInit() { files = new LinkedHashSet<>(files); } if (!files.contains(outputFileName)) { - if (!outputFile.delete()) { + if (overwriteOutput && !outputFile.delete()) { getLog().error("Cannot delete " + outputFile + " will append instead"); } } @@ -142,6 +161,11 @@ protected void logInit() { } } + /** + * Log a line to the console and/or the output file as configured. + * @param error if {@code true} log as error, otherwise as info + * @param line the line to log + */ protected void logLine(boolean error, String line) { if (logOutput) { if (error) { @@ -165,6 +189,7 @@ protected void logLine(boolean error, String line) { } /** + * Get the offset of the configured output line width compared to the default with of 80. * @return Offset of the configured output line width compared to the default with of 80. */ protected int getOutputLineWidthOffset() { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java index 7a03e2ce93..5d3bde36a7 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java @@ -144,7 +144,7 @@ public abstract class AbstractVersionsReport extends AbstractMavenReport { protected ReportRendererFactory rendererFactory; /** - * (injected) map of {@link Wagon} instances + * (injected) map of {@link Wagon} instances per protocol * * @since 2.14.0 */ @@ -154,6 +154,14 @@ public abstract class AbstractVersionsReport extends AbstractMavenReport { // --------------------- GETTER / SETTER METHODS --------------------- + /** + * Creates a new instance. + * @param i18n a {@link I18N} instance + * @param artifactFactory a {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of {@link Wagon} instances per protocol + * @param rendererFactory a {@link ReportRendererFactory} instance + */ protected AbstractVersionsReport( I18N i18n, ArtifactFactory artifactFactory, @@ -167,6 +175,12 @@ protected AbstractVersionsReport( this.rendererFactory = rendererFactory; } + /** + * Returns the configured {@link VersionsHelper} instance, creating it lazily. + * + * @return the {@link VersionsHelper} + * @throws MavenReportException if the helper cannot be created due to a MojoExecutionException + */ public synchronized VersionsHelper getHelper() throws MavenReportException { if (helper == null) { try { @@ -195,7 +209,6 @@ public synchronized VersionsHelper getHelper() throws MavenReportException { } return helper; } - /** * {@inheritDoc} */ @@ -251,10 +264,20 @@ public String getText(Locale locale, String key) { return i18n.getString(getOutputPath(), locale, key); } + /** + * Whether to allow snapshots when searching for the latest version of an artifact. + * + * @return {@code true} if snapshots should be allowed when searching for newer versions of artifacts. + */ public Boolean getAllowSnapshots() { return this.allowSnapshots; } + /** + * Getter the {@link I18N} instance. + * + * @return an {@link I18N} instance + */ public I18N getI18n() { return i18n; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java index a7b087b696..e2b92bd3cf 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java @@ -21,7 +21,6 @@ import javax.inject.Inject; import javax.xml.stream.XMLStreamException; -import javax.xml.transform.TransformerException; import java.io.File; import java.io.IOException; @@ -87,6 +86,7 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { protected RepositorySystem repositorySystem; /** + * The reactor projects for the current build. * @since 1.0-alpha-1 */ @Parameter(defaultValue = "${reactorProjects}", required = true, readonly = true) @@ -98,7 +98,7 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { * @since 1.0-alpha-3 */ @Parameter(property = "maven.version.rules.serverId", defaultValue = "serverId") - private String serverId; + protected String serverId; /** * URI of a ruleSet file containing the rules that control how to compare @@ -108,7 +108,7 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { * @since 1.0-alpha-3 */ @Parameter(property = "maven.version.rules") - private String rulesUri; + protected String rulesUri; /** * Controls whether a backup pom should be created. @@ -131,6 +131,9 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { @Parameter(defaultValue = "${session}", required = true, readonly = true) protected MavenSession session; + /** + * The current mojo execution. + */ @Parameter(defaultValue = "${mojoExecution}", required = true, readonly = true) protected MojoExecution mojoExecution; @@ -182,16 +185,28 @@ public abstract class AbstractVersionsUpdaterMojo extends AbstractMojo { protected Set ignoredVersions; /** - * (injected) map of {@link Wagon} instances + * (injected) map of {@link Wagon} instances per protocol * * @since 2.14.0 */ protected final Map wagonMap; + /** + * An {@link ArtifactFactory} instance. + */ protected final ArtifactFactory artifactFactory; // --------------------- GETTER / SETTER METHODS --------------------- + /** + * Constructor used by Mojos that update versions. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap map of wagon instances + * @param changeRecorders map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject protected AbstractVersionsUpdaterMojo( ArtifactFactory artifactFactory, @@ -205,8 +220,25 @@ protected AbstractVersionsUpdaterMojo( this.changeRecorders = changeRecorders; } + /** + * {@code true} if snapshots should be allowed when searching for newer versions of artifacts. This can be + * overridden on a per-call basis by passing a non-{@code null} value to the + * {@link #findLatestVersion(Artifact, VersionRange, Boolean, boolean)} method. + * + * Default is {@code false} for all Mojos except {@code versions:use-latest-versions} and + * {@code versions:use-latest-releases} where it is {@code true} + * @return {@code true} if snapshots should be allowed when searching for newer versions of artifacts. + * @since 1.0-alpha-1 + * @see #findLatestVersion(Artifact, VersionRange, Boolean, boolean) + */ protected abstract boolean getAllowSnapshots(); + /** + * Returns the configured {@link VersionsHelper} instance, creating it lazily. + * + * @return the {@link VersionsHelper} + * @throws MojoExecutionException if the helper cannot be created + */ public synchronized VersionsHelper getHelper() throws MojoExecutionException { if (helper == null) { RuleService ruleService = new RulesServiceBuilder() @@ -252,6 +284,12 @@ public void setProject(MavenProject project) { this.project = project; } + /** + * Gets the version of the project being processed. + * + * @return the version of the project being processed or {@code null} if no project is set + * @since 1.0-alpha-1 + */ public String getVersion() { return getProject() == null ? null : getProject().getVersion(); } @@ -336,7 +374,7 @@ protected void process(File outFile) throws MojoExecutionException, MojoFailureE saveChangeRecorderResults(); } catch (IOException e) { getLog().error(e); - } catch (VersionRetrievalException | XMLStreamException | TransformerException e) { + } catch (VersionRetrievalException | XMLStreamException e) { throw new MojoExecutionException(e.getMessage(), e); } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CommitMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CommitMojo.java index 1a262799a6..80c140dcae 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CommitMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CommitMojo.java @@ -46,6 +46,12 @@ public class CommitMojo extends AbstractMojo { @Parameter(defaultValue = "${project}", required = true, readonly = true) private MavenProject project; + /** + * Creates a new instance. + */ + public CommitMojo() {} + + @Override public void execute() throws MojoExecutionException, MojoFailureException { Path outFile = project.getFile().toPath(); Path backupFile = outFile.getParent().resolve(outFile.getFileName() + ".versionsBackup"); diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java index 47b02c15f0..f0cd509503 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/CompareDependenciesMojo.java @@ -149,6 +149,15 @@ public class CompareDependenciesMojo extends AbstractVersionsDependencyUpdaterMo // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param projectBuilder a {@link ProjectBuilder} instance + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public CompareDependenciesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesAggregateReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesAggregateReport.java index c7c5150d36..6f11719976 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesAggregateReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesAggregateReport.java @@ -46,6 +46,15 @@ aggregator = true) public class DependencyUpdatesAggregateReport extends AbstractDependencyUpdatesReport { + /** + * Creates a new instance + * + * @param i18n an {@link I18N} instance + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param rendererFactory a {@link ReportRendererFactory} instance + */ @Inject protected DependencyUpdatesAggregateReport( I18N i18n, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReport.java index 59c80c51bd..155e80b16f 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DependencyUpdatesReport.java @@ -43,6 +43,15 @@ @Mojo(name = "dependency-updates-report", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true) public class DependencyUpdatesReport extends AbstractDependencyUpdatesReport { + /** + * Creates a new instance + * + * @param i18n an {@link I18N} instance + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param rendererFactory a {@link ReportRendererFactory} instance + */ @Inject protected DependencyUpdatesReport( I18N i18n, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java index ac0adeed6c..37b73e9f54 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java @@ -26,7 +26,11 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.TreeSet; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; import org.apache.maven.model.Dependency; @@ -36,13 +40,17 @@ 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.ResolverAdapter; import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; +import org.codehaus.mojo.versions.api.internal.DefaultResolverAdapter; import org.codehaus.mojo.versions.api.recording.ChangeRecorder; import org.codehaus.mojo.versions.filtering.WildcardMatcher; import org.codehaus.mojo.versions.internal.DependencyUpdatesLoggingHelper; import org.codehaus.mojo.versions.internal.DependencyUpdatesLoggingHelper.DependencyUpdatesResult; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; +import org.codehaus.mojo.versions.rule.RuleService; +import org.codehaus.mojo.versions.rule.RulesServiceBuilder; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyComparator; import org.codehaus.mojo.versions.utils.MavenProjectUtils; @@ -318,6 +326,15 @@ public class DisplayDependencyUpdatesMojo extends AbstractVersionsDisplayMojo { // --------------------- GETTER / SETTER METHODS --------------------- + /** + * Creates a new instance + * + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public DisplayDependencyUpdatesMojo( ArtifactFactory artifactFactory, @@ -333,28 +350,36 @@ protected boolean getAllowSnapshots() { return allowSnapshots; } + /** + * Whether the given dependency matches the managed dependency. Matching means that + * groupId and artifactId are equal, and if scope, classifier or version is set + * in the managed dependency, they must be equal, too. + * + * @param dependency the dependency to check + * @param managedDependency the managed dependency to check against + * @return true if the dependencies match, false otherwise + */ // open for tests - protected static boolean dependenciesMatch(Dependency dependency, Dependency managedDependency) { - if (!managedDependency.getGroupId().equals(dependency.getGroupId())) { + static boolean dependenciesMatch(Dependency dependency, Dependency managedDependency) { + if (!Objects.equals(managedDependency.getGroupId(), dependency.getGroupId())) { return false; } - if (!managedDependency.getArtifactId().equals(dependency.getArtifactId())) { + if (!Objects.equals(managedDependency.getArtifactId(), dependency.getArtifactId())) { return false; } - if (managedDependency.getScope() == null - || Objects.equals(managedDependency.getScope(), dependency.getScope())) { + if (managedDependency.getScope() != null + && !Objects.equals(managedDependency.getScope(), dependency.getScope())) { return false; } - if (managedDependency.getClassifier() == null - || Objects.equals(managedDependency.getClassifier(), dependency.getClassifier())) { + if (managedDependency.getClassifier() != null + && !Objects.equals(managedDependency.getClassifier(), dependency.getClassifier())) { return false; } - return dependency.getVersion() == null - || managedDependency.getVersion() == null + return managedDependency.getVersion() == null || Objects.equals(managedDependency.getVersion(), dependency.getVersion()); } @@ -373,86 +398,123 @@ public void execute() throws MojoExecutionException, MojoFailureException { logInit(); validateInput(); - Set dependencyManagement; + Set dependencyManagement, dependencies; + ResolverAdapter resolverAdapter = + new DefaultResolverAdapter(artifactFactory, repositorySystem, getLog(), session); + RuleService ruleService = new RulesServiceBuilder() + .withMavenSession(session) + .withWagonMap(wagonMap) + .withServerId(serverId) + .withRulesUri(rulesUri) + .withRuleSet(ruleSet) + .withIgnoredVersions(ignoredVersions) + .withLog(getLog()) + .build(); + Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( + allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()); + DependencyUpdatesLoggingHelper loggingHelper = new DependencyUpdatesLoggingHelper( + getProject(), + getLog(), + artifactFactory, + ruleService, + unchangedSegment, + allowSnapshots, + INFO_PAD_SIZE + getOutputLineWidthOffset(), + verbose); + try { if (processDependencyManagement) { dependencyManagement = filterDependencies( - extractDependenciesFromDependencyManagement( - getProject(), processDependencyManagementTransitive, getLog()), - dependencyManagementIncludes, - dependencyManagementExcludes, - "Dependecy Management", - getLog()); - - logUpdates( - getHelper() - .lookupDependenciesUpdates( - dependencyManagement.stream().filter(d -> d.getVersion() != null), - false, - allowSnapshots), - "Dependency Management"); + extractDependenciesFromDependencyManagement( + getProject(), processDependencyManagementTransitive, getLog()), + dependencyManagementIncludes, + dependencyManagementExcludes, + "Dependency Management", + getLog()) + .stream() + .filter(d -> d.getVersion() != null) + .collect(Collectors.toSet()); } else { dependencyManagement = emptySet(); } + if (processDependencies) { + dependencies = filterDependencies( + getProject().getDependencies().stream() + .filter(dep -> dependencyManagement.stream() + .noneMatch(depMan -> dependenciesMatch(dep, depMan))) + .filter(dep -> showVersionless + || MavenProjectUtils.dependencyVersionLocalToReactor(dep)) + .collect(Collectors.toSet()), + dependencyIncludes, + dependencyExcludes, + "Dependencies", + getLog()) + .stream() + .filter(d -> d.getVersion() != null) + .collect(Collectors.toSet()); + } else { + dependencies = emptySet(); + } + + Map dependencyArtifactVersionsMap = resolverAdapter.resolveDependencyVersions( + Stream.concat(dependencyManagement.stream(), dependencies.stream()) + .collect(Collectors.toSet()), + false, + true); + if (processDependencies) { logUpdates( - getHelper() - .lookupDependenciesUpdates( - filterDependencies( - getProject().getDependencies().stream() - .filter(dep -> dependencyManagement.stream() - .noneMatch(depMan -> - dependenciesMatch(dep, depMan))) - .filter(dep -> showVersionless - || MavenProjectUtils - .dependencyVersionLocalToReactor(dep)) - .collect( - () -> new TreeSet<>( - DependencyComparator.INSTANCE), - Set::add, - Set::addAll), - dependencyIncludes, - dependencyExcludes, - "Dependencies", - getLog()) - .stream() - .filter(d -> d.getVersion() != null), - false, - allowSnapshots), + loggingHelper, + dependencies.stream() + .collect(Collectors.toMap( + Function.identity(), + dependencyArtifactVersionsMap::get, + (v1, v2) -> v1, + () -> new TreeMap<>(DependencyComparator.INSTANCE))), "Dependencies"); } - if (processPluginDependenciesInPluginManagement) { + + if (processDependencyManagement) { logUpdates( - getHelper() - .lookupDependenciesUpdates( - filterDependencies( - extractPluginDependenciesFromPluginsInPluginManagement( - getProject()), - pluginManagementDependencyIncludes, - pluginManagementDependencyExcludes, - "Plugin Management Dependencies", - getLog()) - .stream() - .filter(d -> d.getVersion() != null), - false, - allowSnapshots), - "pluginManagement of plugins"); + loggingHelper, + dependencyManagement.stream() + .collect(Collectors.toMap( + Function.identity(), + dependencyArtifactVersionsMap::get, + (v1, v2) -> v1, + () -> new TreeMap<>(DependencyComparator.INSTANCE))), + "Dependency Management"); + } + + if (processPluginDependenciesInPluginManagement) { + SortedMap updates = resolverAdapter.resolveDependencyVersions( + filterDependencies( + extractPluginDependenciesFromPluginsInPluginManagement(getProject()), + pluginManagementDependencyIncludes, + pluginManagementDependencyExcludes, + "Plugin Management Dependencies", + getLog()) + .stream() + .filter(d -> d.getVersion() != null) + .collect(Collectors.toSet()), + false, + true); + logUpdates(loggingHelper, updates, "pluginManagement of plugins"); } if (processPluginDependencies) { - logUpdates( - getHelper() - .lookupDependenciesUpdates( - filterDependencies( - extractDependenciesFromPlugins(getProject()), - pluginDependencyIncludes, - pluginDependencyExcludes, - "Plugin Dependencies", - getLog()) - .stream() - .filter(d -> d.getVersion() != null), - false, - allowSnapshots), - "Plugin Dependencies"); + SortedMap updates = resolverAdapter.resolveDependencyVersions( + filterDependencies( + extractDependenciesFromPlugins(getProject()), + pluginDependencyIncludes, + pluginDependencyExcludes, + "Plugin Dependencies", + getLog()) + .stream() + .filter(d -> d.getVersion() != null) + .collect(Collectors.toSet()), + true, + false); + logUpdates(loggingHelper, updates, "Plugin Dependencies"); } } catch (VersionRetrievalException e) { throw new MojoExecutionException(e.getMessage(), e); @@ -486,17 +548,11 @@ static void validateGAVList(List gavList, int numSections, String argume } } - private void logUpdates(Map versionMap, String section) { - Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( - allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()); - DependencyUpdatesResult updates = DependencyUpdatesLoggingHelper.getDependencyUpdates( - getProject(), - versionMap, - allowSnapshots, - unchangedSegment, - INFO_PAD_SIZE + getOutputLineWidthOffset(), - verbose); - + private void logUpdates( + DependencyUpdatesLoggingHelper loggingHelper, + SortedMap versionMap, + String section) { + DependencyUpdatesResult updates = loggingHelper.getDependencyUpdates(versionMap); if (verbose) { if (updates.getUsingLatest().isEmpty()) { if (!updates.getWithUpdates().isEmpty()) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java index 79a21cba17..da2e6de41c 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java @@ -24,9 +24,12 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.SortedMap; +import java.util.TreeMap; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.model.Dependency; import org.apache.maven.model.Extension; import org.apache.maven.plugin.MojoExecutionException; @@ -35,15 +38,20 @@ 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.ResolverAdapter; import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.api.VersionRetrievalException; +import org.codehaus.mojo.versions.api.internal.DefaultResolverAdapter; 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.internal.DependencyUpdatesLoggingHelper; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; +import org.codehaus.mojo.versions.rule.RuleService; +import org.codehaus.mojo.versions.rule.RulesServiceBuilder; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.codehaus.mojo.versions.utils.DependencyBuilder; +import org.codehaus.mojo.versions.utils.DependencyComparator; import org.codehaus.mojo.versions.utils.ExtensionUtils; import org.codehaus.mojo.versions.utils.SegmentUtils; import org.eclipse.aether.RepositorySystem; @@ -153,6 +161,15 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { @Parameter(property = "allowSnapshots", defaultValue = "false") protected boolean allowSnapshots; + /** + * Creates a new instance. + * + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public DisplayExtensionUpdatesMojo( ArtifactFactory artifactFactory, @@ -180,6 +197,28 @@ public void execute() throws MojoExecutionException, MojoFailureException { DependencyFilter includeFilter = DependencyFilter.parseFrom(extensionIncludes); DependencyFilter excludeFilter = DependencyFilter.parseFrom(extensionExcludes); + ResolverAdapter resolverAdapter = + new DefaultResolverAdapter(artifactFactory, repositorySystem, getLog(), session); + RuleService ruleService = new RulesServiceBuilder() + .withMavenSession(session) + .withWagonMap(wagonMap) + .withServerId(serverId) + .withRulesUri(rulesUri) + .withRuleSet(ruleSet) + .withIgnoredVersions(ignoredVersions) + .withLog(getLog()) + .build(); + Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( + allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()); + DependencyUpdatesLoggingHelper loggingHelper = new DependencyUpdatesLoggingHelper( + getProject(), + getLog(), + artifactFactory, + ruleService, + unchangedSegment, + allowSnapshots, + INFO_PAD_SIZE + getOutputLineWidthOffset(), + verbose); try { Stream coreExtensions = @@ -195,7 +234,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { .withVersion(e.getVersion()) .build()) .filter(includeFilter::matchersMatch) - .filter(excludeFilter::matchersDontMatch) + .filter(dependency -> !excludeFilter.matchersMatch(dependency)) .collect(Collectors.toSet()); if (dependencies.isEmpty()) { @@ -203,7 +242,18 @@ public void execute() throws MojoExecutionException, MojoFailureException { return; } - logUpdates(getHelper().lookupDependenciesUpdates(dependencies.stream(), true, true, allowSnapshots)); + SortedMap versionMap = + resolverAdapter.resolveDependencyVersions(dependencies, true, true); + if (!allowSnapshots) { + versionMap = versionMap.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> new ArtifactVersions(e.getValue()).filter(v -> !ArtifactUtils.isSnapshot(v)), + (v1, v2) -> v1, + () -> new TreeMap<>(DependencyComparator.INSTANCE))); + } + + logUpdates(loggingHelper, versionMap); } catch (IOException | XMLStreamException | TransformerException e) { throw new MojoExecutionException(e.getMessage()); } catch (VersionRetrievalException e) { @@ -211,17 +261,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } - private void logUpdates(Map versionMap) { - Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( - allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()); - DependencyUpdatesLoggingHelper.DependencyUpdatesResult updates = - DependencyUpdatesLoggingHelper.getDependencyUpdates( - getProject(), - versionMap, - allowSnapshots, - unchangedSegment, - INFO_PAD_SIZE + getOutputLineWidthOffset(), - verbose); + private void logUpdates( + DependencyUpdatesLoggingHelper loggingHelper, SortedMap versionMap) { + DependencyUpdatesLoggingHelper.DependencyUpdatesResult updates = loggingHelper.getDependencyUpdates(versionMap); if (verbose) { if (updates.getUsingLatest().isEmpty()) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java index 1e653b5d0a..ba3bdda39b 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojo.java @@ -59,6 +59,9 @@ @Mojo(name = "display-parent-updates", threadSafe = true) public class DisplayParentUpdatesMojo extends AbstractVersionsDisplayMojo { + /** + * Length of the message part of the output, used to calculate padding. + */ public static final int MESSAGE_LENGTH = 68; // ------------------------------ FIELDS ------------------------------ @@ -141,6 +144,15 @@ public class DisplayParentUpdatesMojo extends AbstractVersionsDisplayMojo { // -------------------------- OTHER METHODS -------------------------- + /** + * Creates a new instance + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the wagon map + * @param changeRecorders the change recorders + * @throws MojoExecutionException if any + */ @Inject public DisplayParentUpdatesMojo( ArtifactFactory artifactFactory, @@ -221,6 +233,18 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } + /** + * Resolves the target version of the parent artifact. + * The initial version may be a version range. If it is, the resolved version will be + * restricted by that range. + * + * @param initialVersion the initial version, may be a version range + * @return the resolved target version, or {@code null} if no update is available + * @throws MojoExecutionException if an error occurred + * @throws VersionRetrievalException if an error occurred while retrieving versions + * @throws InvalidVersionSpecificationException if the version specification is invalid + * @throws InvalidSegmentException if the segment configuration is invalid + */ protected ArtifactVersion resolveTargetVersion(String initialVersion) throws MojoExecutionException, VersionRetrievalException, InvalidVersionSpecificationException, InvalidSegmentException { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java index a20ec4c6e7..dec30be549 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojo.java @@ -130,9 +130,15 @@ public class DisplayPluginUpdatesMojo extends AbstractVersionsDisplayMojo { */ private static final String FROM_SUPER_POM = "(from super-pom) "; + /** + * String to flag a plugin version being forced by a parent pom. + */ public static final Pattern PATTERN_PROJECT_PLUGIN = Pattern.compile( "/project(/profiles/profile)?" + "((/build(/pluginManagement)?)|(/reporting))" + "/plugins/plugin"); + /** + * The path to the super-pom. + */ public static final String SUPERPOM_PATH = "org/apache/maven/model/pom-4.0.0.xml"; /** @@ -180,6 +186,19 @@ public class DisplayPluginUpdatesMojo extends AbstractVersionsDisplayMojo { // --------------------- GETTER / SETTER METHODS --------------------- + /** + * Creates a new instance. + * + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param projectBuilder a {@link ProjectBuilder} instance + * @param wagonMap a map of wagon providers per protocol + * @param lifecycleExecutor the (injected) instance of {@link LifecycleExecutor} + * @param modelInterpolator the (injected) instance of {@link ModelInterpolator} + * @param runtimeInformation the (injected) instance of {@link RuntimeInformation} + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject @SuppressWarnings("checkstyle:ParameterNumber") public DisplayPluginUpdatesMojo( @@ -267,7 +286,7 @@ private Map getSuperPomPluginManagement() { curState = pathStack.pop(); } } - } catch (IOException | XMLStreamException | TransformerException e) { + } catch (IOException | XMLStreamException e) { // ignore } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java index 79ba06e104..ee89448620 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojo.java @@ -75,7 +75,7 @@ public class DisplayPropertyUpdatesMojo extends AbstractVersionsDisplayMojo { * @since 1.0-alpha-3 */ @Parameter - private Property[] properties; + private List properties; /** * A comma separated list of properties to update. @@ -151,6 +151,15 @@ public class DisplayPropertyUpdatesMojo extends AbstractVersionsDisplayMojo { // -------------------------- OTHER METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public DisplayPropertyUpdatesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java index c51db0ea66..0dbc3540b8 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ForceReleasesMojo.java @@ -86,6 +86,15 @@ public class ForceReleasesMojo extends AbstractVersionsDependencyUpdaterMojo { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public ForceReleasesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java index 9ab4d1a1be..057392bc2b 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/LockSnapshotsMojo.java @@ -94,6 +94,15 @@ public class LockSnapshotsMojo extends AbstractVersionsDependencyUpdaterMojo { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public LockSnapshotsMojo( ArtifactFactory artifactFactory, @@ -153,6 +162,16 @@ protected void update(MutableXMLStreamReader pom) } } + /** + * Lock the snapshot dependency versions if they are timestamped snapshots. If a dependency is part of the reactor + * or if the dependency is not a timestamped snapshot, no action is taken. + * + * @param pom the pom to update + * @param dependencies the dependencies to check + * @throws XMLStreamException thrown if XML streaming fails + * @throws MojoExecutionException thrown if retrieval of {@link VersionsHelper} fails + * @throws VersionResolutionException thrown if version resolution fails + */ protected void lockSnapshots(MutableXMLStreamReader pom, Collection dependencies) throws XMLStreamException, MojoExecutionException, VersionResolutionException { for (Dependency dep : dependencies) { @@ -192,6 +211,15 @@ protected void lockSnapshots(MutableXMLStreamReader pom, Collection } } + /** + * Lock the parent snapshot version if it is a timestamped snapshot. If the parent is part of the reactor + * or if the parent is not a timestamped snapshot, no action is taken. + * + * @param pom the pom to update + * @param parent the parent project + * @throws XMLStreamException thrown if XML streaming fails + * @throws VersionResolutionException thrown if version resolution fails + */ protected void lockParentSnapshot(MutableXMLStreamReader pom, MavenProject parent) throws XMLStreamException, VersionResolutionException { if (parent == null) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ParentUpdatesReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ParentUpdatesReport.java index 310bd779e3..5eba5959e2 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ParentUpdatesReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ParentUpdatesReport.java @@ -47,6 +47,15 @@ @Mojo(name = "parent-updates-report", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true) public class ParentUpdatesReport extends AbstractVersionsReport { + /** + * Creates a new report instance. + * + * @param i18n an {@link I18N} instance + * @param artifactFactory a {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon implementations + * @param rendererFactory a {@link ReportRendererFactory} instance + */ @Inject protected ParentUpdatesReport( I18N i18n, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesAggregateReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesAggregateReport.java index 8e1841efce..c132cfab9e 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesAggregateReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesAggregateReport.java @@ -45,6 +45,14 @@ aggregator = true) public class PluginUpdatesAggregateReport extends AbstractPluginUpdatesReport { + /** + * Creates a new report instance. + * @param i18n an {@link I18N} instance + * @param artifactFactory a {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon implementations + * @param rendererFactory a {@link ReportRendererFactory} instance + */ @Inject protected PluginUpdatesAggregateReport( I18N i18n, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReport.java index de026c9567..9648ca2408 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PluginUpdatesReport.java @@ -42,6 +42,15 @@ @Mojo(name = "plugin-updates-report", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true) public class PluginUpdatesReport extends AbstractPluginUpdatesReport { + /** + * Creates a new report instance. + * + * @param i18n an {@link I18N} instance + * @param artifactFactory a {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon implementations + * @param rendererFactory a {@link ReportRendererFactory} instance + */ @Inject protected PluginUpdatesReport( I18N i18n, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesAggregateReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesAggregateReport.java index 7c859e7ac3..df5cf60de1 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesAggregateReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesAggregateReport.java @@ -49,6 +49,15 @@ aggregator = true) public class PropertyUpdatesAggregateReport extends AbstractPropertyUpdatesReport { + /** + * Creates a new report instance. + * + * @param i18n an {@link I18N} instance + * @param artifactFactory a {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon implementations + * @param rendererFactory a {@link ReportRendererFactory} instance + */ @Inject protected PropertyUpdatesAggregateReport( I18N i18n, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReport.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReport.java index db9403846d..e282ef7706 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReport.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/PropertyUpdatesReport.java @@ -44,6 +44,15 @@ */ @Mojo(name = "property-updates-report", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true) public class PropertyUpdatesReport extends AbstractPropertyUpdatesReport { + /** + * Creates a new report instance. + * + * @param i18n an {@link I18N} instance + * @param artifactFactory a {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon implementations + * @param rendererFactory a {@link ReportRendererFactory} instance + */ @Inject protected PropertyUpdatesReport( I18N i18n, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java index 979c27cf02..7a5b68cdfe 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/ResolveRangesMojo.java @@ -162,6 +162,15 @@ public class ResolveRangesMojo extends AbstractVersionsDependencyUpdaterMojo { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public ResolveRangesMojo( ArtifactFactory artifactFactory, @@ -277,8 +286,8 @@ private void resolveRanges(MutableXMLStreamReader pom, Collection de } if (StringUtils.isBlank(dep.getVersion())) { - throw new MojoExecutionException( - "Found invalid managed dependency " + toString(dep) + " without a version"); + getLog().info("Found managed dependency " + toString(dep) + " without a version"); + continue; } if (isHandledByProperty(dep)) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/RevertMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/RevertMojo.java index a364ccb037..d06f2dba6e 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/RevertMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/RevertMojo.java @@ -72,6 +72,11 @@ public class RevertMojo extends AbstractMojo { */ protected final ProjectBuilder projectBuilder; + /** + * Creates a new instance. + * + * @param projectBuilder the project builder + */ @Inject protected RevertMojo(ProjectBuilder projectBuilder) { this.projectBuilder = projectBuilder; diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java index 157c774f59..c8913489a2 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetMojo.java @@ -261,6 +261,17 @@ public class SetMojo extends AbstractVersionsUpdaterMojo { */ protected final ProjectBuilder projectBuilder; + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param projectBuilder the project builder + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @param prompter the prompter + * @throws MojoExecutionException when things go wrong + */ @Inject public SetMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java index 8ce3c29f1c..8561918291 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetPropertyMojo.java @@ -24,7 +24,9 @@ import java.io.IOException; import java.util.Arrays; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -102,6 +104,17 @@ public class SetPropertyMojo extends AbstractVersionsUpdaterMojo { @Parameter(property = "allowSnapshots", defaultValue = "false") protected boolean allowSnapshots; + // --------------------------- CONSTRUCTORS --------------------------- + + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public SetPropertyMojo( ArtifactFactory artifactFactory, @@ -126,7 +139,7 @@ protected boolean getAllowSnapshots() { */ protected void update(MutableXMLStreamReader pom) throws MojoExecutionException, MojoFailureException, XMLStreamException { - Property[] propertiesConfig; + List propertiesConfig; String properties; if (!isEmpty(propertiesVersionsFile)) { logWrongConfigWarning(); @@ -150,7 +163,7 @@ protected void update(MutableXMLStreamReader pom) propertyConfig.setVersion(newVersion); return propertyConfig; }) - .toArray(Property[]::new); + .collect(Collectors.toList()); properties = property; } else { throw new MojoExecutionException("Please provide either 'property' or 'propertiesVersionsFile' parameter."); @@ -158,7 +171,7 @@ protected void update(MutableXMLStreamReader pom) update(pom, propertiesConfig, properties); } - private void update(MutableXMLStreamReader pom, Property[] propertiesConfig, String properties) + private void update(MutableXMLStreamReader pom, List propertiesConfig, String properties) throws MojoExecutionException, XMLStreamException { Map propertyVersions = this.getHelper() .getVersionPropertiesMap(VersionsHelper.VersionPropertiesMapRequest.builder() diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java index 31765688d8..9820acc569 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/SetScmTagMojo.java @@ -72,6 +72,15 @@ public class SetScmTagMojo extends AbstractVersionsUpdaterMojo { @Parameter(property = "allowSnapshots", defaultValue = "false") protected boolean allowSnapshots; + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public SetScmTagMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java index a5ced10df4..43b5caedd7 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UnlockSnapshotsMojo.java @@ -86,6 +86,15 @@ public class UnlockSnapshotsMojo extends AbstractVersionsDependencyUpdaterMojo { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UnlockSnapshotsMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java index 48d49813dc..9f33bf0324 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateChildModulesMojo.java @@ -74,6 +74,15 @@ public class UpdateChildModulesMojo extends AbstractVersionsUpdaterMojo { @Parameter(property = "allowSnapshots", defaultValue = "false") protected boolean allowSnapshots; + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UpdateChildModulesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java index 0f28e57e93..a03d32b3bc 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java @@ -141,6 +141,15 @@ public class UpdateParentMojo extends UseLatestVersionsMojoBase { // -------------------------- OTHER METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UpdateParentMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java index 354831f5e4..bdc96f971c 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojo.java @@ -22,6 +22,7 @@ import javax.inject.Inject; import javax.xml.stream.XMLStreamException; +import java.util.List; import java.util.Map; import org.apache.maven.plugin.MojoExecutionException; @@ -50,7 +51,7 @@ public class UpdatePropertiesMojo extends UpdatePropertiesMojoBase { * @since 1.0-alpha-3 */ @Parameter - private Property[] properties; + private List properties; /** * A comma separated list of properties to update. @@ -92,6 +93,14 @@ public class UpdatePropertiesMojo extends UpdatePropertiesMojoBase { @Parameter(property = "processParent", defaultValue = "false") private boolean processParent = false; + /** + * Creates a new instance + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UpdatePropertiesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java index 78d6f55cb8..ecabf70cfe 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertiesMojoBase.java @@ -139,6 +139,15 @@ public abstract class UpdatePropertiesMojoBase extends AbstractVersionsDependenc @Parameter(property = "processParent", defaultValue = "false") private boolean processParent = false; + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ public UpdatePropertiesMojoBase( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, @@ -153,6 +162,12 @@ protected boolean getAllowSnapshots() { return allowSnapshots; } + /** + * Update the given POM. This method is called for each POM to be updated. + * @param pom the pom to update. + * @param propertyVersions the properties to update + * @throws XMLStreamException it's not possible to read/write the POM + */ protected void update(MutableXMLStreamReader pom, Map propertyVersions) throws XMLStreamException { for (Map.Entry entry : propertyVersions.entrySet()) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertyMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertyMojo.java index b27490b2a7..58bad52115 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertyMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UpdatePropertyMojo.java @@ -22,6 +22,7 @@ import javax.inject.Inject; import javax.xml.stream.XMLStreamException; +import java.util.Collections; import java.util.Map; import org.apache.maven.plugin.MojoExecutionException; @@ -95,6 +96,15 @@ public class UpdatePropertyMojo extends UpdatePropertiesMojoBase { @Parameter(property = "processParent", defaultValue = "false") private boolean processParent = false; + /** + * Creates a new instance + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the wagon map + * @param changeRecorders the change recorders + * @throws MojoExecutionException if any + */ @Inject public UpdatePropertyMojo( ArtifactFactory artifactFactory, @@ -135,13 +145,11 @@ protected void update(MutableXMLStreamReader pom) getHelper() .getVersionPropertiesMap(VersionsHelper.VersionPropertiesMapRequest.builder() .withMavenProject(getProject()) - .withPropertyDefinitions(new Property[] { - new Property(property) { - { - setVersion(newVersion); - } + .withPropertyDefinitions(Collections.singletonList(new Property(property) { + { + setVersion(newVersion); } - }) + })) .withIncludeProperties(property) .withAutoLinkItems(autoLinkItems) .withIncludeParent(includeParent) diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java index a44ff6236d..ae47bbb2e8 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseDepVersionMojo.java @@ -17,7 +17,6 @@ import javax.inject.Inject; import javax.xml.stream.XMLStreamException; -import javax.xml.transform.TransformerException; import java.io.IOException; import java.io.Writer; @@ -157,6 +156,15 @@ protected boolean getAllowSnapshots() { @Parameter(property = "processProperties", defaultValue = "false") protected boolean processProperties; + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseDepVersionMojo( ArtifactFactory artifactFactory, @@ -215,7 +223,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { .orElse(Charset.defaultCharset())); } propertyBacklog.forEach(p -> getLog().warn("Not updating property ${" + p + "}: defined in parent")); - } catch (IOException | XMLStreamException | TransformerException e) { + } catch (IOException | XMLStreamException e) { throw new MojoFailureException(e.getMessage(), e); } catch (RuntimeException e) { if (e.getCause() instanceof MojoFailureException) { @@ -239,6 +247,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { * used one of these properties. Such a change is not allowed and must be reported instead. * @param charset charset for file writing * @return {@code true} if the file has been changed + * @throws MojoFailureException thrown if a version may not be changed + * @throws MojoExecutionException thrown if a version may not be changed */ protected boolean processModel( ModelNode node, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java index 78b0bc11a6..57bc938551 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java @@ -112,6 +112,15 @@ public class UseLatestReleasesMojo extends UseLatestVersionsMojoBase { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseLatestReleasesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java index ac3169410d..4a381c0a94 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestSnapshotsMojo.java @@ -95,6 +95,15 @@ public class UseLatestSnapshotsMojo extends UseLatestVersionsMojoBase { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseLatestSnapshotsMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java index f8884d744b..f02b538ad9 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java @@ -28,6 +28,7 @@ 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.AbstractVersionDetails; import org.codehaus.mojo.versions.api.recording.ChangeRecorder; import org.codehaus.mojo.versions.utils.ArtifactFactory; import org.eclipse.aether.RepositorySystem; @@ -85,6 +86,15 @@ public class UseLatestVersionsMojo extends UseLatestVersionsMojoBase { @Parameter(property = "allowSnapshots", defaultValue = "false") protected boolean allowSnapshots; + /** + * Whether to allow pre-release versions (alpha, beta, milestone, rc) when searching + * for the latest version of an artifact. + * + * @since 2.20.0 + */ + @Parameter(property = "allowPreReleases", defaultValue = "false") + protected boolean allowPreReleases = false; + /** * Whether to process the dependencies section of the project. * @@ -116,6 +126,15 @@ protected boolean getAllowSnapshots() { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseLatestVersionsMojo( ArtifactFactory artifactFactory, @@ -168,6 +187,9 @@ protected boolean updateFilter(Dependency dep) { @Override protected boolean artifactVersionsFilter(ArtifactVersion ver) { + if (!allowPreReleases) { + return !AbstractVersionDetails.isPreReleaseVersion(ver.toString()); + } return true; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java index e8f44d1215..1e9bf3d727 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java @@ -67,22 +67,70 @@ public abstract class UseLatestVersionsMojoBase extends AbstractVersionsDependen @Parameter(property = "numThreads", defaultValue = "5") private int numThreads = 5; + /** + * Whether snapshots should be allowed when searching for newer versions + * @return {@code true} if snapshots should be allowed when searching for newer versions + */ protected abstract boolean getAllowMajorUpdates(); + /** + * Whether minor updates should be allowed when searching for newer versions + * @return {@code true} if minor updates should be allowed when searching for newer versions + */ protected abstract boolean getAllowMinorUpdates(); + /** + * Whether incremental updates should be allowed when searching for newer versions + * @return {@code true} if incremental updates should be allowed when searching for newer versions + */ protected abstract boolean getAllowIncrementalUpdates(); + /** + * Whether downgrades should be allowed when searching for newer versions + * @return {@code true} if downgrades should be allowed when searching for newer versions + */ protected abstract boolean getAllowDowngrade(); + /** + * Whether snapshots should be allowed when searching for newer versions + * @return {@code true} if snapshots should be allowed when searching for newer versions + */ + protected abstract boolean getAllowSnapshots(); + /** + * A filter for dependencies to be updated. + * + * @param dep the dependency to check + * @return {@code true} if the dependency should be updated, {@code false} otherwise + */ protected abstract boolean updateFilter(Dependency dep); + /** + * A filter for artifact versions to be considered. + * + * @param ver the artifact version to check + * @return {@code true} if the artifact version should be considered, {@code false} otherwise + */ protected abstract boolean artifactVersionsFilter(ArtifactVersion ver); + /** + * Produces a version from a stream of artifact versions. + * + * @param stream the stream of artifact versions + * @return an optional containing the produced version, or an empty optional if no version could be produced + */ protected abstract Optional versionProducer(Stream stream); private final ExecutorService executor = Executors.newFixedThreadPool(numThreads); + /** + * Creates a new instance + * + * @param artifactFactory an {@link ArtifactFactory} instance + * @param repositorySystem a {@link RepositorySystem} instance + * @param wagonMap a map of wagon providers per protocol + * @param changeRecorders a map of change recorders + * @throws MojoExecutionException when things go wrong + */ public UseLatestVersionsMojoBase( ArtifactFactory artifactFactory, RepositorySystem repositorySystem, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java index 2899469da0..9ad6e0ce75 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextReleasesMojo.java @@ -75,6 +75,15 @@ public class UseNextReleasesMojo extends UseLatestVersionsMojoBase { @Parameter(property = "processParent", defaultValue = "false") private boolean processParent = false; + /** + * Creates a new instance + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the wagon map + * @param changeRecorders the change recorders + * @throws MojoExecutionException if any + */ @Inject public UseNextReleasesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java index ca3272eb1b..d287907426 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextSnapshotsMojo.java @@ -94,6 +94,15 @@ public class UseNextSnapshotsMojo extends UseLatestVersionsMojoBase { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseNextSnapshotsMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java index 7715de9398..d25b8dd7df 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseNextVersionsMojo.java @@ -89,6 +89,15 @@ protected boolean getAllowSnapshots() { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseNextVersionsMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java index ccd80d6d2e..561d97b7b2 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReactorMojo.java @@ -106,6 +106,15 @@ protected boolean getAllowSnapshots() { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseReactorMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java index c240fae09d..3f7abff466 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseReleasesMojo.java @@ -120,6 +120,15 @@ protected boolean getAllowSnapshots() { // ------------------------------ METHODS -------------------------- + /** + * Creates a new instance. + * + * @param artifactFactory the artifact factory + * @param repositorySystem the repository system + * @param wagonMap the map of wagon implementations + * @param changeRecorders the change recorders + * @throws MojoExecutionException when things go wrong + */ @Inject public UseReleasesMojo( ArtifactFactory artifactFactory, diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java index 086d90f884..c0034894ca 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/internal/DependencyUpdatesLoggingHelper.java @@ -10,12 +10,16 @@ import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.Restriction; import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.codehaus.mojo.versions.DisplayDependencyUpdatesMojo; import org.codehaus.mojo.versions.DisplayExtensionUpdatesMojo; import org.codehaus.mojo.versions.api.ArtifactVersions; import org.codehaus.mojo.versions.api.Segment; import org.codehaus.mojo.versions.ordering.InvalidSegmentException; +import org.codehaus.mojo.versions.rule.RuleService; +import org.codehaus.mojo.versions.rule.RuleServiceUtils; +import org.codehaus.mojo.versions.utils.ArtifactFactory; import static java.util.Optional.empty; import static org.codehaus.mojo.versions.utils.DependencyBuilder.Location.VERSION; @@ -26,10 +30,60 @@ */ public class DependencyUpdatesLoggingHelper { + private final RuleService ruleService; + + private final Optional unchangedSegment; + + private final boolean allowSnapshots; + + private final int maxLineWidth; + + private final boolean displayManagedBy; + + private final MavenProject project; + + private final ArtifactFactory artifactFactory; + + private final Log log; + + /** + * Constructs a new instance. + * + * @param project a {@link MavenProject} object + * @param log a {@link Log} instance + * @param artifactFactory {@link ArtifactFactory} instance + * @param ruleService a {@link RuleService} instance + * @param unchangedSegment the most major version segment that is not to be changed or {@link Optional#empty()} + * if all version segments can be changed + * @param allowSnapshots whether snapshots should be allowed as updates + * @param maxLineWidth maximum line width + * @param displayManagedBy if {@code true}, will display information on the pom managing the given dependency + * for dependencies not managed by the current project + */ + @SuppressWarnings("checkstyle:parameterNumber") + public DependencyUpdatesLoggingHelper( + MavenProject project, + Log log, + ArtifactFactory artifactFactory, + RuleService ruleService, + Optional unchangedSegment, + boolean allowSnapshots, + int maxLineWidth, + boolean displayManagedBy) { + this.project = project; + this.log = log; + this.artifactFactory = artifactFactory; + this.ruleService = ruleService; + this.unchangedSegment = unchangedSegment; + this.allowSnapshots = allowSnapshots; + this.maxLineWidth = maxLineWidth; + this.displayManagedBy = displayManagedBy; + } + /** * @return {@code true} if the version of the dependency is in the project */ - private static boolean dependencyVersionLocalToProject(MavenProject project, Dependency dependency) { + private boolean dependencyVersionLocalToProject(Dependency dependency) { return dependency .getLocation(VERSION.toString()) .getSource() @@ -38,36 +92,27 @@ private static boolean dependencyVersionLocalToProject(MavenProject project, Dep } /** - * Compiles a {@link DependencyUpdatesResult} object containing dependency updates for the given dependency map - * and the given unchanged segment. - * @param project a {@link MavenProject} object + *

Compiles a {@link DependencyUpdatesResult} object containing dependency updates for the given dependency map + * and the given unchanged segment.

+ *

The resulting dependencies are filtered using the include/exclude rules from the {@link RuleService}.

+ * * @param updates map of available versions per dependency - * @param allowSnapshots whether snapshots should be allowed as updates - * @param unchangedSegment the most major segment not allowed to be updated or {@code Optional.empty()} if - * all segments are allowed to be updated - * @param maxLineWith maximum line width - * @param displayManagedBy if {@code true}, will display information on the pom managing the given dependency - * for dependencies not managed by the current project * @return a {@link DependencyUpdatesResult} object containing the result */ - public static DependencyUpdatesResult getDependencyUpdates( - MavenProject project, - Map updates, - boolean allowSnapshots, - Optional unchangedSegment, - int maxLineWith, - boolean displayManagedBy) { + public DependencyUpdatesResult getDependencyUpdates(Map updates) { List withUpdates = new ArrayList<>(); List usingCurrent = new ArrayList<>(); for (Map.Entry entry : updates.entrySet()) { Dependency dep = entry.getKey(); - ArtifactVersions versions = entry.getValue(); + ArtifactVersions versions = RuleServiceUtils.filterByRuleService( + dep.getGroupId(), dep.getArtifactId(), entry.getValue(), ruleService, log); + String left = " " + ArtifactUtils.versionlessKey(versions.getArtifact()) + " "; String currentVersion; Optional latestVersion; if (versions.getCurrentVersion() != null) { currentVersion = versions.getCurrentVersion() - + (!displayManagedBy || dependencyVersionLocalToProject(project, dep) + + (!displayManagedBy || dependencyVersionLocalToProject(dep) ? "" : " (managed by " + dep.getLocation(VERSION.toString()) @@ -97,15 +142,16 @@ public static DependencyUpdatesResult getDependencyUpdates( latestVersion = Optional.of(newVersionRestriction) .map(restriction -> versions.getNewestVersion(restriction, allowSnapshots)); } + String right = " " + latestVersion.map(v -> currentVersion + " -> " + v).orElse(currentVersion); List t = latestVersion.isPresent() ? withUpdates : usingCurrent; - if (right.length() + left.length() + 3 > maxLineWith) { + if (right.length() + left.length() + 3 > maxLineWidth) { t.add(left + "..."); - t.add(StringUtils.leftPad(right, maxLineWith)); + t.add(StringUtils.leftPad(right, maxLineWidth)); } else { - t.add(StringUtils.rightPad(left, maxLineWith - right.length(), ".") + right); + t.add(StringUtils.rightPad(left, maxLineWidth - right.length(), ".") + right); } } @@ -128,11 +174,15 @@ public List getWithUpdates() { public interface DependencyUpdatesResult { /** + * Returns the list of dependencies using the latest version available (i.e. no update available) + * * @return Dependencies using the latest version */ List getUsingLatest(); /** + * Returns the list of dependencies with updates available (i.e. not using the latest version) + * * @return Dependencies with updates available */ List getWithUpdates(); diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/AbstractVersionsReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/AbstractVersionsReportRenderer.java index 9f2c9ae94c..0fd67cf03b 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/AbstractVersionsReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/AbstractVersionsReportRenderer.java @@ -61,14 +61,33 @@ public abstract class AbstractVersionsReportRenderer extends VersionsReportRe */ protected T model; + /** + * Cache for newest updates (used for summary rendering) + */ protected final ArtifactVersionsCache newestUpdateCache = new ArtifactVersionsCache(AbstractVersionDetails::getReportNewestUpdate); + /** + * Cache for all updates (used for details rendering) + */ protected final ArtifactVersionsCache allUpdatesCache = new ArtifactVersionsCache(AbstractVersionDetails::getReportUpdates); + /** + * Table header attributes + */ protected final SinkEventAttributes headerAttributes = new SinkEventAttributeSet(SinkEventAttributes.WIDTH, "30%"); + /** + * Creates a new renderer instance. + * + * @param i18n internationalization helper + * @param sink the Doxia sink to write to + * @param locale the locale + * @param bundleName resource bundle name + * @param model the model to render + * @param allowSnapshots whether snapshots are allowed in displays + */ protected AbstractVersionsReportRenderer( I18N i18n, Sink sink, Locale locale, String bundleName, T model, boolean allowSnapshots) { super(sink, i18n, locale, bundleName, allowSnapshots); @@ -175,6 +194,11 @@ protected void renderIcon(boolean success) { */ protected abstract void renderDetails(); + /** + * Renders the summary table of artifact updates. If there are no artifact updates, nothing is rendered. + * @param contents the map of dependencies to their details + * @param hasScope whether the artifacts have scopes + */ protected void renderSummaryTable(Map contents, boolean hasScope) { startTable(); @@ -191,6 +215,11 @@ protected void renderSummaryTable(Map contents, bo endTable(); } + /** + * Renders the header row of the summary table. + * @param hasScope whether the artifacts have scopes + * @param hasType whether the artifacts have types + */ protected void renderSummaryTableHeader(boolean hasScope, boolean hasType) { renderTableHeaderCells("report.status", "report.groupId", "report.artifactId", "report.currentVersion"); if (hasScope) { @@ -203,6 +232,12 @@ protected void renderSummaryTableHeader(boolean hasScope, boolean hasType) { "report.latestSubIncremental", "report.latestIncremental", "report.latestMinor", "report.latestMajor"); } + /** + * Renders one summary table row for the given artifact and its details. + * @param artifact the artifact to render + * @param details the details of the artifact to render + * @param includeScope whether to include the scope column + */ protected void renderSummaryTableRow(Dependency artifact, ArtifactVersions details, boolean includeScope) { details.setCurrentVersion(artifact.getVersion()); ArtifactVersion[] allUpdates = allUpdatesCache.get(details, empty(), isAllowSnapshots()); @@ -225,7 +260,9 @@ protected void renderSummaryTableRow(Dependency artifact, ArtifactVersions detai } /** - * Renders the newest versions for the given artifact. + * Renders the newest versions for the given artifact. If there is no newer version for a given segment, + * the corresponding cell is left empty. + * * @param details the artifact for which to render the newest versions. */ protected void renderNewestVersions(AbstractVersionDetails details) { @@ -235,6 +272,13 @@ protected void renderNewestVersions(AbstractVersionDetails details) { renderBoldCell(newestUpdateCache.get(details, of(MAJOR), isAllowSnapshots())); } + /** + * Renders the details table for an artifact. If there are no updates, only the current version is shown. + * + * @param artifact the artifact being detailed + * @param details the details of the artifact + * @param includeScope whether to include the scope row + */ protected void renderDependencyDetailTable(Dependency artifact, ArtifactVersions details, boolean includeScope) { ArtifactVersion[] allUpdates = allUpdatesCache.get(details, empty(), isAllowSnapshots()); boolean upToDate = allUpdates == null || allUpdates.length == 0; @@ -259,6 +303,7 @@ protected void renderDependencyDetailTable(Dependency artifact, ArtifactVersions /** * Renders a row of two cells, the first cell being an header and the second cell being a non-header cell. + * * @param textKey the key of the text to be rendered. * @param textValue the value of the text to be rendered. */ diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java index 983247002a..d0f47d3a35 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/DependencyUpdatesReportRenderer.java @@ -30,11 +30,21 @@ import org.codehaus.plexus.i18n.I18N; /** + * A renderer for Dependency updates reports, using a {@link DependencyUpdatesModel}. * @param type of the model * @since 1.0-beta-1 */ public class DependencyUpdatesReportRenderer extends AbstractVersionsReportRenderer { + /** + * Creates a new instance. + * @param i18n an {@link I18N} instance + * @param sink the {@link Sink} to render to + * @param locale the locale to render in + * @param bundleName the resource bundle name to use + * @param model object containing the updates model + * @param allowSnapshots whether snapshots should be included + */ public DependencyUpdatesReportRenderer( I18N i18n, Sink sink, Locale locale, String bundleName, K model, boolean allowSnapshots) { super(i18n, sink, locale, bundleName, model, allowSnapshots); @@ -61,6 +71,13 @@ protected void renderManagementSummaryTable() { "report.overview.noDependencyManagement"); } + /** + * Renders a table with the given title and contents. If the contents are empty, a message is rendered instead. + * + * @param titleKey the resource bundle key for the title of the table + * @param contents the contents of the table + * @param emptyKey the resource bundle key for the message to render if the contents are empty + */ protected void renderTable(String titleKey, Map contents, String emptyKey) { startSection(getText(titleKey)); @@ -77,6 +94,12 @@ protected OverviewStats computeOverviewStats() { return OverviewStats.fromUpdates(model.getAllUpdates().values(), newestUpdateCache, isAllowSnapshots()); } + /** + * Renders the details for a given dependency. If there are no updates, nothing is rendered. + * + * @param artifact the dependency + * @param details the details of the dependency + */ protected void renderDependencyDetail(Dependency artifact, ArtifactVersions details) { startSection(ArtifactUtils.versionlessKey(artifact.getGroupId(), artifact.getArtifactId())); renderDependencyDetailTable(artifact, details, true); diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/OverviewStats.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/OverviewStats.java index f7fc0febdd..68a7b5d4bc 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/OverviewStats.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/OverviewStats.java @@ -50,6 +50,11 @@ public class OverviewStats { private int upToDate; + /** + * Creates a new instance. + */ + public OverviewStats() {} + /** * Creates a {@linkplain OverviewStats} instance based on the collection of version updates in * the argument @@ -82,48 +87,95 @@ public static T from return (T) stats; } + /** + * Retrieves the newest update for the given details, segment and snapshot allowance from the cache. + * If the cache is null, an assertion error is thrown. + * + * @param cache if not null, cache to retrieve the version information, initialised with + * the {@link ArtifactVersions#getNewestUpdateWithinSegment(Optional, boolean)} update information + * @param details details of the artifact to check + * @param segment segment to check + * @param allowSnapshots whether snapshots should be included + * @param subclass of {@linkplain AbstractVersionDetails} + * @return the newest update or null if there is no update within the segment + */ protected static ArtifactVersion getNewestUpdate( ArtifactVersionsCache cache, V details, Optional segment, boolean allowSnapshots) { assert cache != null; return cache.get(details, segment, allowSnapshots); } + /** + * Gets the number of updates available within the major segment + * @return number of updates available within the major segment + */ public int getMajor() { return major; } + /** + * Increments the number of updates available within the major segment + */ public void incrementMajor() { major++; } + /** + * Gets the number of updates available within the minor segment + * @return number of updates available within the minor segment + */ public int getMinor() { return minor; } + /** + * Increments the number of updates available within the minor segment + */ public void incrementMinor() { minor++; } + /** + * Gets the number of updates available within the incremental segment + * @return number of updates available within the incremental segment + */ public int getIncremental() { return incremental; } + /** + * Increments the number of updates available within the incremental segment + */ public void incrementIncremental() { incremental++; } + /** + * Gets the number of updates available within the sub-incremental segment + * @return number of updates available within the sub-incremental segment + */ public int getAny() { return any; } + /** + * Increments the number of updates available within the sub-incremental segment + */ public void incrementAny() { any++; } + /** + * Gets the number of up-to-date artifacts + * @return number of up-to-date artifacts + */ public int getUpToDate() { return upToDate; } + /** + * Increments the number of up-to-date artifacts + */ public void incrementUpToDate() { upToDate++; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ParentUpdatesReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ParentUpdatesReportRenderer.java index 2fd21c554f..e42b5ddfa6 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ParentUpdatesReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ParentUpdatesReportRenderer.java @@ -26,9 +26,20 @@ import org.codehaus.plexus.i18n.I18N; /** + * A renderer for Parent updates reports, using {@link ParentUpdatesModel} as model. * @since 1.0-beta-1 */ public class ParentUpdatesReportRenderer extends DependencyUpdatesReportRenderer { + /** + * Creates a new instance. + * + * @param i18n an {@link I18N} instance + * @param sink the {@link Sink} to render to + * @param locale the locale to render in + * @param bundleName the resource bundle name to use + * @param model object containing the updates model + * @param allowSnapshots whether snapshots should be included + */ public ParentUpdatesReportRenderer( I18N i18n, Sink sink, Locale locale, String bundleName, ParentUpdatesModel model, boolean allowSnapshots) { super(i18n, sink, locale, bundleName, model, allowSnapshots); diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginOverviewStats.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginOverviewStats.java index 7f8fcdc693..9e772c6909 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginOverviewStats.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginOverviewStats.java @@ -34,16 +34,31 @@ import static org.codehaus.mojo.versions.api.Segment.MINOR; import static org.codehaus.mojo.versions.api.Segment.SUBINCREMENTAL; +/** + * Extension of the {@linkplain OverviewStats} adding dependency stats + */ public class PluginOverviewStats extends OverviewStats { /** * Extension of the {@linkplain OverviewStats} adding dependency stats */ private int dependencies; + /** + * Creates a new instance. + */ + public PluginOverviewStats() {} + + /** + * Gets the number of plugins with dependency updates available + * @return number of plugins with dependency updates available + */ public int getDependencies() { return dependencies; } + /** + * Increments the number of plugins with dependency updates available + */ public void incrementDependencies() { dependencies++; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java index 16beebc60d..d9a9e9106f 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PluginUpdatesReportRenderer.java @@ -35,10 +35,21 @@ import static java.util.Optional.empty; /** + * A renderer for Plugin updates reports, using a {@link PluginUpdatesModel}. * @since 1.0-beta-1 */ public class PluginUpdatesReportRenderer extends AbstractVersionsReportRenderer { + /** + * Creates a new instance. + * + * @param i18n an {@link I18N} instance + * @param sink the {@link Sink} to render to + * @param locale the locale to render in + * @param bundleName the resource bundle name to use + * @param model object containing the updates model + * @param allowSnapshots whether snapshots should be included + */ public PluginUpdatesReportRenderer( I18N i18n, Sink sink, Locale locale, String bundleName, PluginUpdatesModel model, boolean allowSnapshots) { super(i18n, sink, locale, bundleName, model, allowSnapshots); @@ -49,6 +60,7 @@ protected void renderSummaryTable() { renderTable("report.overview.plugin", model.getArtifactUpdates(), "report.overview.noPlugin"); } + @Override protected void renderManagementSummaryTable() { renderTable( "report.overview.pluginManagement", @@ -83,6 +95,10 @@ private void renderTable(String titleKey, Map endSection(); } + /** + * Renders the summary table of plugin updates. If there are no plugin updates, nothing is rendered. + * @param contents the map of plugins to their details + */ protected void renderSummaryTable(Map contents) { startTable(); @@ -122,6 +138,12 @@ protected void renderOverviewTableRow(T stats) { false); } + /** + * Renders a summary table row for a plugin. If there are no plugin updates, nothing is rendered. + * + * @param artifact the plugin artifact + * @param details the plugin update details + */ protected void renderSummaryTableRow(Dependency artifact, PluginUpdatesDetails details) { boolean upToDate = !details.isUpdateAvailable(); diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java index 273790a940..02d900f4d6 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/PropertyUpdatesReportRenderer.java @@ -34,9 +34,20 @@ import static java.util.Optional.empty; /** + * A renderer for Property updates reports, using a {@link PropertyUpdatesModel}. * @since 1.0-beta-1 */ public class PropertyUpdatesReportRenderer extends AbstractVersionsReportRenderer { + /** + * Creates a new instance. + * + * @param i18n an {@link I18N} instance + * @param sink the {@link Sink} to render to + * @param locale the locale to render in + * @param bundleName the resource bundle name to use + * @param model object containing the updates model + * @param allowSnapshots whether snapshots should be included + */ public PropertyUpdatesReportRenderer( I18N i18n, Sink sink, @@ -63,6 +74,10 @@ protected void renderDetails() { model.getAllUpdates().forEach(this::renderPropertyDetail); } + /** + * Renders the table of property updates. If there are no property updates, a suitable message is shown. + * @param contents the map of properties to their details + */ protected void renderTable(Map contents) { startSection(getText("report.overview.property")); @@ -74,6 +89,10 @@ protected void renderTable(Map contents) { endSection(); } + /** + * Renders the summary table of property updates. If there are no property updates, nothing is rendered. + * @param contents the map of properties to their details + */ protected void renderSummaryTable(Map contents) { startTable(); @@ -106,6 +125,11 @@ private void renderPropertySummaryTableRow(Property property, PropertyVersions d sink.tableRow_(); } + /** + * Renders the details table for a property. If there are no updates, only the current version is shown. + * @param property the property being detailed + * @param details the details of the property + */ protected void renderPropertyDetailTable(Property property, PropertyVersions details) { ArtifactVersion[] allUpdates = allUpdatesCache.get(details, empty(), isAllowSnapshots()); boolean upToDate = allUpdates == null || allUpdates.length == 0; diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java index fd9afa4f46..915bc74da6 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/ReportRendererFactoryImpl.java @@ -39,15 +39,42 @@ @Named @Singleton public class ReportRendererFactoryImpl implements ReportRendererFactory { + /** + * The report name for the dependency updates report + */ public static final String DEPENDENCY_UPDATES_REPORT = "dependency-updates-report"; + /** + * The report name for the aggregate dependency updates report + */ public static final String DEPENDENCY_UPDATES_AGGREGATE_REPORT = "dependency-updates-aggregate-report"; + /** + * The report name for the plugin updates report + */ public static final String PLUGIN_UPDATES_REPORT = "plugin-updates-report"; + /** + * The report name for the aggregate plugin updates report + */ public static final String PLUGIN_UPDATES_AGGREGATE_REPORT = "plugin-updates-aggregate-report"; + /** + * The report name for the property updates report + */ public static final String PROPERTY_UPDATES_REPORT = "property-updates-report"; + /** + * The report name for the aggregate property updates report + */ public static final String PROPERTY_UPDATES_AGGREGATE_REPORT = "property-updates-aggregate-report"; + /** + * The report name for the parent updates report + */ public static final String PARENT_UPDATES_REPORT = "parent-updates-report"; + private final I18N i18N; + /** + * Creates a new instance + * + * @param i18N an {@link I18N} instance + */ @Inject public ReportRendererFactoryImpl(I18N i18N) { this.i18N = i18N; diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java index b46f2ce204..7136a5e7dd 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/VersionsReportRendererBase.java @@ -55,6 +55,16 @@ public abstract class VersionsReportRendererBase extends AbstractMavenReportRend */ protected String bundleName; + /** + * Creates a new report renderer instance. + * + * @param sink the sink to render to, must not be {@code null} + * @param i18n the i18n component, must not be {@code null} + * @param locale the locale we are rendering for, must not be {@code null} + * @param bundleName the name of the resource bundle to use, must not be {@code null} + * @param allowSnapshots whether snapshots should be included + * @throws IllegalArgumentException if any of the parameters are {@code null} + */ protected VersionsReportRendererBase( Sink sink, I18N i18n, Locale locale, String bundleName, boolean allowSnapshots) { super(sink); @@ -83,14 +93,27 @@ public String getText(String key) { return i18n.getString(bundleName, locale, key); } + /** + * Renders a warning icon. + */ protected void renderWarningIcon() { sink.figureGraphics("images/icon_warning_sml.gif"); } + /** + * Renders a success icon. + */ protected void renderSuccessIcon() { sink.figureGraphics("images/icon_success_sml.gif"); } + /** + * Compares two artifact versions for equality. + * + * @param v1 the first artifact version to compare, may be {@code null} + * @param v2 the second artifact version to compare, may be {@code null} + * @return {@code true} if the two versions are considered equal, {@code false} otherwise + */ protected boolean equals(ArtifactVersion v1, ArtifactVersion v2) { return v1 == v2 || (v1 != null && v1.equals(v2)) diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/AbstractUpdatesModel.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/AbstractUpdatesModel.java index 9aa4380535..0cb9b0c6bb 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/AbstractUpdatesModel.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/AbstractUpdatesModel.java @@ -36,6 +36,17 @@ public abstract class AbstractUpdatesModel { private final Map artifactManagementUpdates; private final Map allUpdates; + /** + *

Creates a new instance of the model, based on the provided map of artifact (dependency or plugin) updates + * per artifact, provided map of dependency or plugin management updates, and provided list of all updates.

+ *

The model uses {@link Dependency} to model dependencies or plugins, hereby called artifacts, and + * therefore requires an adapter function the {@code supplier} argument, converting the type of artifact + * to a {@link Dependency}.

+ * @param artifactUpdates map of artifact (dependency or plugin) updates per artifact + * @param artifactManagementUpdates map of artifact (dependency or plugin) management updates per artifact + * @param supplier function converting the given "artifact" type (plugin, dependency) to a {@link Dependency} + * @param concrete {@link ArtifactVersions} subclass, used by the provided maps + */ public AbstractUpdatesModel( Map artifactUpdates, Map artifactManagementUpdates, Function supplier) { this.artifactUpdates = artifactUpdates.entrySet().stream() @@ -54,14 +65,26 @@ public AbstractUpdatesModel( allUpdates.putAll(this.artifactUpdates); } + /** + * Returns a map of updates per "artifact" (here modeled by {@link Dependency}). + * @return map of updates + */ public Map getArtifactUpdates() { return artifactUpdates; } + /** + * Returns a map of "management updates" per "artifact" (here modeled by {@link Dependency}). + * @return map of "management updates" + */ public Map getArtifactManagementUpdates() { return artifactManagementUpdates; } + /** + * Returns a map of all updates per "artifact" (here modeled by {@link Dependency}). + * @return map of all updates + */ public Map getAllUpdates() { return allUpdates; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/DependencyUpdatesModel.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/DependencyUpdatesModel.java index 5a264cc3c7..6e79b7eeeb 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/DependencyUpdatesModel.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/DependencyUpdatesModel.java @@ -29,6 +29,12 @@ * Model class for using with the {@linkplain ReportRenderer} API */ public class DependencyUpdatesModel extends AbstractUpdatesModel { + /** + * Creates a new model instance with the given maps of dependency updates. + * + * @param dependencyUpdates the map of dependencies to their updates + * @param dependencyManagementUpdates the map of dependency management entries to their updates + */ public DependencyUpdatesModel( Map dependencyUpdates, Map dependencyManagementUpdates) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/ParentUpdatesModel.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/ParentUpdatesModel.java index fe2a1ade99..e1eaa854c6 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/ParentUpdatesModel.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/ParentUpdatesModel.java @@ -30,6 +30,12 @@ * Model class for using with the {@linkplain ReportRenderer} API */ public class ParentUpdatesModel extends DependencyUpdatesModel { + /** + * Creates a new model instance with the given parent and its updates. + * + * @param parent the parent dependency + * @param dependencyUpdates the updates for the parent + */ public ParentUpdatesModel(Dependency parent, ArtifactVersions dependencyUpdates) { super(singletonMap(parent, dependencyUpdates), emptyMap()); } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java index 1997d22259..9171186e2f 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/model/PropertyUpdatesModel.java @@ -32,11 +32,20 @@ public class PropertyUpdatesModel { private final Map allUpdates; + /** + * Creates a new model instance with the given comparator and map of property updates. + * @param comparator the comparator to use for ordering the properties + * @param propertyUpdates the map of properties to their updates + */ public PropertyUpdatesModel(PropertyComparator comparator, Map propertyUpdates) { this.allUpdates = new TreeMap<>(comparator); this.allUpdates.putAll(propertyUpdates); } + /** + * Gets the map of all property updates. + * @return the map of all property updates + */ public Map getAllUpdates() { return allUpdates; } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/util/AggregateReportUtils.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/util/AggregateReportUtils.java index d2791ffc87..9270032faa 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/util/AggregateReportUtils.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/reporting/util/AggregateReportUtils.java @@ -30,6 +30,10 @@ * */ public class AggregateReportUtils { + private AggregateReportUtils() { + // utility class + } + /** * Returns an aggregated list of {@link MavenProject} for the given project. * diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/DependencyUpdatesXmlReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/DependencyUpdatesXmlReportRenderer.java index b9ba455cbe..fcac864674 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/DependencyUpdatesXmlReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/DependencyUpdatesXmlReportRenderer.java @@ -70,6 +70,7 @@ public class DependencyUpdatesXmlReportRenderer implements ReportRenderer { * Creates a new instance * @param model object containing the updates model * @param outputFile output file for the report + * @param allowSnapshots whether snapshot versions should be considered */ public DependencyUpdatesXmlReportRenderer(DependencyUpdatesModel model, Path outputFile, boolean allowSnapshots) { this.model = model; diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PluginUpdatesXmlReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PluginUpdatesXmlReportRenderer.java index da549b72fc..e979ec98ce 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PluginUpdatesXmlReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PluginUpdatesXmlReportRenderer.java @@ -67,9 +67,11 @@ public class PluginUpdatesXmlReportRenderer implements ReportRenderer { private final boolean allowSnapshots; /** - * Creates a new instance + * Creates a new instance. + * * @param model object containing the updates model * @param outputFile output file for the report + * @param allowSnapshots whether snapshots should be included */ public PluginUpdatesXmlReportRenderer(PluginUpdatesModel model, Path outputFile, boolean allowSnapshots) { this.model = model; diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PropertyUpdatesXmlReportRenderer.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PropertyUpdatesXmlReportRenderer.java index afca1e3d75..06e5c7cbea 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PropertyUpdatesXmlReportRenderer.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/xml/PropertyUpdatesXmlReportRenderer.java @@ -68,6 +68,7 @@ public class PropertyUpdatesXmlReportRenderer implements ReportRenderer { * Creates a new instance * @param model object containing the updates model * @param outputFile output file for the report + * @param allowSnapshots whether snapshots should be included */ public PropertyUpdatesXmlReportRenderer(PropertyUpdatesModel model, Path outputFile, boolean allowSnapshots) { this.model = model; diff --git a/versions-maven-plugin/src/site/markdown/examples/display-dependency-updates.md b/versions-maven-plugin/src/site/markdown/examples/display-dependency-updates.md index 31d26752d6..a74307573d 100644 --- a/versions-maven-plugin/src/site/markdown/examples/display-dependency-updates.md +++ b/versions-maven-plugin/src/site/markdown/examples/display-dependency-updates.md @@ -80,6 +80,19 @@ or: ``` +Alternatively, with greater readability, you can write: + +```xml + + ... + + .*-M.* + .*-alpha.* + + ... + +``` + in your project config. That will result in the following output. Instead of: ```shell diff --git a/versions-maven-plugin/src/site/markdown/faq.md b/versions-maven-plugin/src/site/markdown/faq.md index 1244d5b43f..ab6ad086f4 100644 --- a/versions-maven-plugin/src/site/markdown/faq.md +++ b/versions-maven-plugin/src/site/markdown/faq.md @@ -91,6 +91,18 @@ or: ``` +Alternatively, with greater readability, you can write: + +```xml + + ... + + .*-M.* + + ... + +``` + in your project config. See [Issue #258](https://github.com/mojohaus/versions/issues/258) and [the documentation for ignoredVersions](https://www.mojohaus.org/versions/versions-maven-plugin/display-dependency-updates-mojo.html#ignoredVersions) diff --git a/versions-maven-plugin/src/site/site.xml b/versions-maven-plugin/src/site/site.xml index cfdab72785..8ed31255a8 100644 --- a/versions-maven-plugin/src/site/site.xml +++ b/versions-maven-plugin/src/site/site.xml @@ -26,7 +26,7 @@ - + diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java index 092c2a7bdb..50c948fd84 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojoTest.java @@ -24,6 +24,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; +import org.apache.maven.model.Dependency; import org.apache.maven.model.InputLocation; import org.apache.maven.model.InputSource; import org.apache.maven.model.Model; @@ -513,7 +514,7 @@ public void testShowVersionlessFalse() throws Exception { } }); mojo.execute(); - assertThat(Files.exists(tempFile.getPath()), is(false)); + assertThat(Files.readAllBytes(tempFile.getPath()).length, is(0)); } } @@ -620,4 +621,116 @@ public void testProblemCausingArtifact() throws Exception { assertThat(vre.getArtifact().map(Artifact::getArtifactId).orElse(""), equalTo("problem-causing-artifact")); } } + + @Test + public void testOverwriteOutput() throws Exception { + testOutputFileOverwrite(true); + } + + @Test + public void testOverwriteOutputFalse() throws Exception { + testOutputFileOverwrite(false); + } + + private void testOutputFileOverwrite(boolean overwrite) throws Exception { + try (CloseableTempFile tempFile = new CloseableTempFile("display-dependency-updates")) { + for (int i = 0; i < 2; ++i) { + new DisplayDependencyUpdatesMojo( + artifactFactory, + mockAetherRepositorySystem(new HashMap() { + { + put("default-dependency", new String[] {"1.0.0", "2.0.0"}); + } + }), + null, + null) { + { + setProject(createProject()); + processDependencies = true; + processDependencyManagement = false; + dependencyIncludes = singletonList(WildcardMatcher.WILDCARD); + dependencyExcludes = emptyList(); + outputFile = tempFile.getPath().toFile(); + overwriteOutput = overwrite; + setPluginContext(new HashMap<>()); + + session = mockMavenSession(); + mojoExecution = mock(MojoExecution.class); + } + }.execute(); + } + + List output = Files.readAllLines(tempFile.getPath()); + assertThat( + output + " should contain 2 strings matching 1.0.0 -> 2.0.0", + output.stream() + .filter(line -> line.contains("1.0.0 -> 2.0.0")) + .count(), + is(overwrite ? 1L : 2L)); + } + } + + private static Dependency createManagedDependency( + Dependency prototype, String version, String scope, String classifier) { + return DependencyBuilder.newBuilder() + .withGroupId(prototype.getGroupId()) + .withArtifactId(prototype.getArtifactId()) + .withVersion(version) + .withScope(scope) + .withClassifier(classifier) + .build(); + } + + public void testDependenciesMatchTestScope() { + Dependency dependency = DependencyBuilder.newBuilder() + .withGroupId("default-group") + .withArtifactId("default-artifact") + .withVersion("1.0.0") + .withScope("compile") + .withClassifier("sources") + .build(); + + assertTrue(DisplayDependencyUpdatesMojo.dependenciesMatch( + dependency, createManagedDependency(dependency, null, null, null))); + assertTrue(DisplayDependencyUpdatesMojo.dependenciesMatch( + dependency, createManagedDependency(dependency, "1.0.0", null, null))); + assertTrue(DisplayDependencyUpdatesMojo.dependenciesMatch( + dependency, createManagedDependency(dependency, null, "compile", null))); + assertTrue(DisplayDependencyUpdatesMojo.dependenciesMatch( + dependency, createManagedDependency(dependency, null, null, "sources"))); + assertTrue(DisplayDependencyUpdatesMojo.dependenciesMatch( + dependency, createManagedDependency(dependency, null, null, "sources"))); + } + + @Test + public void testShouldOnlyShowUpdates() throws Exception { + try (CloseableTempFile tempFile = new CloseableTempFile("display-dependency-updates")) { + new DisplayDependencyUpdatesMojo( + artifactFactory, + mockAetherRepositorySystem(new HashMap() { + { + put("default-dependency", new String[] {"0.0.1", "0.0.2", "1.0.0"}); + } + }), + null, + null) { + { + setProject(createProject()); + allowMajorUpdates = true; + processDependencies = true; + processDependencyManagement = false; + dependencyIncludes = singletonList(WildcardMatcher.WILDCARD); + dependencyExcludes = emptyList(); + allowSnapshots = true; + outputFile = tempFile.getPath().toFile(); + setPluginContext(new HashMap<>()); + + session = mockMavenSession(); + mojoExecution = mock(MojoExecution.class); + } + }.execute(); + + assertThat(String.join("", Files.readAllLines(tempFile.getPath())), not(containsString("1.0.0"))); + } + } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java index 71b8cc3862..6c87b3c48b 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java @@ -21,6 +21,7 @@ import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; +import java.util.List; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; @@ -54,6 +55,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -312,4 +314,29 @@ public void testProblemCausingArtifact() assertThat(vre.getArtifact().map(Artifact::getArtifactId).orElse(""), equalTo("problem-causing-artifact")); } } + + @Test + public void testLatestVersion() + throws MojoExecutionException, MojoFailureException, IOException, IllegalAccessException { + setVariableValueToObject(mojo, "extensionExcludes", emptyList()); + setVariableValueToObject(mojo, "extensionIncludes", singletonList("*")); + mojo.getProject().setBuild(new Build()); + mojo.getProject() + .getBuild() + .setExtensions(Collections.singletonList(ExtensionBuilder.newBuilder() + .withGroupId("default-group") + .withArtifactId("artifactC") + .withVersion("1.0.0") + .build())); + + try (MockedStatic pomHelper = mockStatic(PomHelper.class)) { + pomHelper + .when(() -> PomHelper.getChildModels(ArgumentMatchers.any(MavenProject.class), any())) + .then(i -> Collections.singletonMap(null, ((MavenProject) i.getArgument(0)).getModel())); + mojo.execute(); + } + + List output = Files.readAllLines(tempPath); + assertThat(output, hasItem(containsString("No extensions have newer versions."))); + } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java index 8d23d08f86..2e60b913e0 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayParentUpdatesMojoTest.java @@ -22,6 +22,7 @@ import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; +import java.util.List; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; @@ -55,7 +56,9 @@ import static org.codehaus.mojo.versions.utils.MockUtils.mockArtifactHandlerManager; import static org.codehaus.mojo.versions.utils.MockUtils.mockMavenSession; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -411,4 +414,19 @@ public void testProblemCausingArtifact() throws MojoFailureException { assertThat(vre.getArtifact().map(Artifact::getArtifactId).orElse(""), equalTo("problem-causing-artifact")); } } + + @Test + public void testLatestVersion() throws Exception { + mojo.getProject().setParent(new MavenProject() { + { + setGroupId("default-group"); + setArtifactId("parent-artifact"); + setVersion("1.0.0"); + } + }); + mojo.allowSnapshots = false; + mojo.execute(); + List output = Files.readAllLines(tempFile); + assertThat(output, hasItem(containsString("The parent project is the latest version"))); + } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojoTest.java index d8df28e074..377362690b 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPluginUpdatesMojoTest.java @@ -183,4 +183,18 @@ public void testProblemCausingArtifact() throws Exception { assertThat(vre.getArtifact().map(Artifact::getArtifactId).orElse(""), equalTo("problem-causing-artifact")); } } + + @Test + public void testLatestVersion() throws Exception { + Files.copy( + Paths.get("src/test/resources/org/codehaus/mojo/display-plugin-updates/updates-only.xml"), + tempDir.resolve("pom.xml")); + + DisplayPluginUpdatesMojo mojo = createMojo(); + mojo.execute(); + + List output = Files.readAllLines(outputPath); + assertThat( + output, hasItem(containsString("All plugins with a version specified are using the latest versions."))); + } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojoTest.java index 9cbb954934..df15348141 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayPropertyUpdatesMojoTest.java @@ -19,6 +19,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; +import java.util.List; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; @@ -36,6 +37,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.matchesPattern; import static org.hamcrest.Matchers.not; @@ -156,4 +158,22 @@ public void testProblemCausingArtifact() throws Exception { assertThat(vre.getArtifact().map(Artifact::getArtifactId).orElse(""), equalTo("problem-causing-artifact")); } } + + @Test + public void testLatestVersion() throws Exception { + TestUtils.copyDir( + Paths.get("src/test/resources/org/codehaus/mojo/display-property-updates/updates-only"), tempDir); + DisplayPropertyUpdatesMojo mojo = (DisplayPropertyUpdatesMojo) + mojoRule.lookupConfiguredMojo(tempDir.toFile(), "display-property-updates"); + mojo.outputEncoding = UTF_8; + mojo.outputFile = tempFile.toFile(); + mojo.setPluginContext(new HashMap<>()); + mojo.repositorySystem = mockAetherRepositorySystem(); + mojo.execute(); + + List output = Files.readAllLines(tempFile); + assertThat( + output, + hasItem(containsString("All version properties are referencing the newest version available."))); + } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java index 7a85257449..fc7b67d9b1 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java @@ -237,4 +237,57 @@ public void testPoisonDependencyVersion() hasItem(new DefaultDependencyVersionChange( "default-group", "dependency-artifact", "1.1.1-SNAPSHOT", "1.1.0"))); } + + @Test + public void testDontUpgradeToPreReleaseByDefault() + throws MojoExecutionException, XMLStreamException, MojoFailureException, IllegalAccessException, + VersionRetrievalException { + mojo.getProject() + .getModel() + .setDependencies(Collections.singletonList(DependencyBuilder.newBuilder() + .withGroupId("default-group") + .withArtifactId("pre-release-artifact") + .withVersion("1.0.0") + .withType("pom") + .withClassifier("default") + .withScope(SCOPE_COMPILE) + .build())); + + // Use all defaults to test that allowPreReleases=false (default) filters out pre-releases + + tryUpdate(); + // Should upgrade to 1.1.0, not 1.2.0-beta1 (pre-release should be filtered out by default) + // Available: 1.2.0-beta1, 1.1.0, 1.0.0 + // With allowPreReleases=false (default), beta is excluded and 1.1.0 is selected + assertThat( + changeRecorder.getChanges(), + hasItem(new DefaultDependencyVersionChange("default-group", "pre-release-artifact", "1.0.0", "1.1.0"))); + } + + @Test + public void testUpgradeToPreReleaseWhenAllowed() + throws MojoExecutionException, XMLStreamException, MojoFailureException, IllegalAccessException, + VersionRetrievalException { + mojo.getProject() + .getModel() + .setDependencies(Collections.singletonList(DependencyBuilder.newBuilder() + .withGroupId("default-group") + .withArtifactId("pre-release-artifact") + .withVersion("1.0.0") + .withType("pom") + .withClassifier("default") + .withScope(SCOPE_COMPILE) + .build())); + + setVariableValueToObject(mojo, "allowPreReleases", true); + + tryUpdate(); + // When allowPreReleases is true, beta version can be selected + // Available: 1.2.0-beta1, 1.1.0, 1.0.0 + // Beta version 1.2.0-beta1 is highest and will be selected + assertThat( + changeRecorder.getChanges(), + hasItem(new DefaultDependencyVersionChange( + "default-group", "pre-release-artifact", "1.0.0", "1.2.0-beta1"))); + } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java index 0c3387d206..86cdd1cfa2 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTestBase.java @@ -83,6 +83,7 @@ protected RepositorySystem createRepositorySystem() { "1.1.1.1-SNAPSHOT", "1.1.1.0", "1.1.1.0-SNAPSHOT", "1.0.0.0", "1.0.0.0-SNAPSHOT", "0.9.0.0" }); put("other-artifact", new String[] {"1.0", "2.0", "2.0-SNAPSHOT"}); + put("pre-release-artifact", new String[] {"1.2.0-beta1", "1.1.0", "1.0.0"}); } }); } diff --git a/versions-maven-plugin/src/test/resources/org/codehaus/mojo/display-plugin-updates/updates-only.xml b/versions-maven-plugin/src/test/resources/org/codehaus/mojo/display-plugin-updates/updates-only.xml new file mode 100644 index 0000000000..9a5ca1b92c --- /dev/null +++ b/versions-maven-plugin/src/test/resources/org/codehaus/mojo/display-plugin-updates/updates-only.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + test-group + test-artifact + DEVELOP-SNAPSHOT + + + + + default-group + default-plugin + 1.0.0 + + + + + diff --git a/versions-maven-plugin/src/test/resources/org/codehaus/mojo/display-property-updates/updates-only/pom.xml b/versions-maven-plugin/src/test/resources/org/codehaus/mojo/display-property-updates/updates-only/pom.xml new file mode 100644 index 0000000000..507a9e3434 --- /dev/null +++ b/versions-maven-plugin/src/test/resources/org/codehaus/mojo/display-property-updates/updates-only/pom.xml @@ -0,0 +1,19 @@ + + 4.0.0 + default-group + parent + 1.0.0 + pom + + + 1.0.0 + + + + + default-group + artifactC + ${ver} + + + diff --git a/versions-model-report/pom.xml b/versions-model-report/pom.xml index d4123ba9da..511d9b6dc8 100644 --- a/versions-model-report/pom.xml +++ b/versions-model-report/pom.xml @@ -4,7 +4,7 @@ org.codehaus.mojo.versions versions - 2.19.1 + 2.20.1 versions-model-report @@ -68,4 +68,18 @@ + + + + + maven-javadoc-plugin + + all,-missing + + -quiet + + + + + diff --git a/versions-model/pom.xml b/versions-model/pom.xml index d202884e54..f0b5eba468 100644 --- a/versions-model/pom.xml +++ b/versions-model/pom.xml @@ -4,7 +4,7 @@ org.codehaus.mojo.versions versions - 2.19.1 + 2.20.1 versions-model @@ -72,4 +72,19 @@ + + + + + maven-javadoc-plugin + + all,-missing + + -quiet + + + + + + diff --git a/versions-test/pom.xml b/versions-test/pom.xml index d0c0be91b5..5a6f5f19fe 100644 --- a/versions-test/pom.xml +++ b/versions-test/pom.xml @@ -22,7 +22,7 @@ org.codehaus.mojo.versions versions - 2.19.1 + 2.20.1 versions-test @@ -70,4 +70,18 @@ + + + + + maven-javadoc-plugin + + + -Werror + + + + + + diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java index a1d67b7236..3b82c2d135 100644 --- a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java +++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/CloseableTempFile.java @@ -20,13 +20,15 @@ import java.nio.file.Path; /** - * Closeable temporary file + * A test utility provided a closeable temporary file, implementing {@link AutoCloseable}, which + * deletes the temporary file on {@link #close()}, typically upon completion of a {@code try-finally} block. */ public class CloseableTempFile implements AutoCloseable { private final Path path; /** - * @return path of the temporary file + * Returns the path of the temporary file. + * @return path of the temporary file. */ public Path getPath() { return path; diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/MockUtils.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/MockUtils.java index 96b1d734db..06a5088449 100644 --- a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/MockUtils.java +++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/MockUtils.java @@ -55,6 +55,9 @@ * Various mock creating utilities */ public class MockUtils { + + private MockUtils() {} + private static final Map DEFAULT_VERSION_MAP = new HashMap() { { put("artifactA", new String[] {"1.0.0", "2.0.0"}); @@ -104,6 +107,13 @@ public static RepositorySystem mockAetherRepositorySystem(Map return repositorySystem; } + /** + * Provides an mocked {@link RepositorySystem} instance for the given map of version updates. + * + * @param repositorySystem mocked {@link RepositorySystem} instance + * @param versionMap a map consisting of artifact name as key of the map, and an array of versions + * which the repository system should return + */ public static void prepareAetherRepositorySystemMockForVersionRange( RepositorySystem repositorySystem, Map versionMap) { try { @@ -133,12 +143,20 @@ private static Version parseVersion(String version) { } } + /** + * Provides a mock of the {@link I18N} bean + * @return mock of the {@link I18N} bean + */ public static I18N mockI18N() { I18N i18n = mock(I18N.class); when(i18n.getString(anyString(), any(), anyString())).thenAnswer(invocation -> invocation.getArgument(2)); return i18n; } + /** + * Provides a mock of the {@link SiteTool} bean + * @return mock of the {@link SiteTool} bean + */ public static SiteTool mockSiteTool() { Artifact skinArtifact = mock(Artifact.class); when(skinArtifact.getId()).thenReturn(""); @@ -151,6 +169,10 @@ public static SiteTool mockSiteTool() { return siteTool; } + /** + * Provides a mock of the {@link ArtifactHandlerManager} bean + * @return mock of the {@link ArtifactHandlerManager} bean + */ public static ArtifactHandlerManager mockArtifactHandlerManager() { ArtifactHandlerManager artifactHandlerManager = mock(ArtifactHandlerManager.class); when(artifactHandlerManager.getArtifactHandler(anyString())).thenAnswer(i -> { diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java index 6b3b7c0fc2..0fe36f09a9 100644 --- a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java +++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestChangeRecorder.java @@ -28,27 +28,68 @@ import org.codehaus.mojo.versions.api.recording.DependencyChangeRecord; import org.codehaus.mojo.versions.api.recording.PropertyChangeRecord; +/** + * A simple {@link ChangeRecorder} implementation used in tests. + *

+ * It records {@link VersionChange} instances reported via dependency or + * property change records into an in-memory list so tests can assert on them. + */ @Named("test") public class TestChangeRecorder implements ChangeRecorder { + /** + * Create a new test change recorder. + */ + public TestChangeRecorder() { + // explicit constructor to provide Javadoc for the no-arg constructor + } + private final List changes = new LinkedList<>(); + /** + * Record a dependency version change. + * + * @param changeRecord the dependency change record containing the version change + */ @Override public void recordChange(DependencyChangeRecord changeRecord) { changes.add(changeRecord.getVersionChange()); } + /** + * Record a property version change. + * + * @param changeRecord the property change record containing the version change + */ @Override public void recordChange(PropertyChangeRecord changeRecord) { changes.add(changeRecord.getVersionChange()); } + /** + * Write a report of recorded changes to the given output path. + *

+ * This test implementation does nothing. + * + * @param outputPath the path where a report would be written + */ @Override public void writeReport(Path outputPath) {} + /** + * Returns the list of recorded version changes in the order they were recorded. + * + * @return an unmodifiable view of the recorded version changes + */ public List getChanges() { return changes; } + /** + * Return a simple map suitable for injection in tests. The map contains a single + * entry with key {@code "none"} mapping to this recorder instance. + * + * @return a map with a single test change recorder entry + */ public Map asTestMap() { HashMap map = new HashMap<>(); map.put("none", this); diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestLog.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestLog.java index daef1f4f1d..8ca35eb9d6 100644 --- a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestLog.java +++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestLog.java @@ -1,16 +1,29 @@ package org.codehaus.mojo.versions.utils; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.apache.commons.lang3.tuple.Triple; import org.apache.maven.plugin.logging.Log; +/** + * A simple {@link Log} stub, collecting logged messages in a queryable list. + */ public class TestLog implements Log { private final List> loggedMessages = new ArrayList<>(); + /** + * Creates an empty new instance + */ + public TestLog() {} + + /** + * Returns an immutable list of logged messages. + * @return immutable copy of the logged messages list. + */ public List> getLoggedMessages() { - return loggedMessages; + return Collections.unmodifiableList(loggedMessages); } @Override @@ -93,10 +106,25 @@ public void error(Throwable throwable) { error(null, throwable); } + /** + * Defines the log level. + */ public enum LogLevel { + /** + * {@code DEBUG} log level + */ DEBUG, + /** + * {@code INFO} log level + */ INFO, + /** + * {@code WARN} log level + */ WARN, + /** + * {@code ERROR} log level + */ ERROR } } diff --git a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestUtils.java b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestUtils.java index 7a97591f2d..dcadecf5ac 100644 --- a/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestUtils.java +++ b/versions-test/src/main/java/org/codehaus/mojo/versions/utils/TestUtils.java @@ -33,6 +33,9 @@ * Auxiliary test utilities */ public class TestUtils { + + private TestUtils() {} + /** * Creates a temporary directory with the given name *