Skip to content

Commit

Permalink
Issue #74: Add display-extension-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
andrzejj0 committed Jan 24, 2023
1 parent 293206e commit eca6dbc
Show file tree
Hide file tree
Showing 9 changed files with 533 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
Expand Down Expand Up @@ -89,6 +90,7 @@
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResolutionException;

import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Optional.empty;
import static java.util.Optional.of;
Expand Down Expand Up @@ -172,12 +174,35 @@ public Log getLog() {
public ArtifactVersions lookupArtifactVersions(
Artifact artifact, VersionRange versionRange, boolean usePluginRepositories)
throws VersionRetrievalException {
return lookupArtifactVersions(artifact, versionRange, usePluginRepositories, !usePluginRepositories);
}

@Override
public ArtifactVersions lookupArtifactVersions(
Artifact artifact, VersionRange versionRange, boolean usePluginRepositories, boolean useProjectRepositories)
throws VersionRetrievalException {
try {
Collection<IgnoreVersion> ignoredVersions = getIgnoredVersions(artifact);
if (!ignoredVersions.isEmpty() && getLog().isDebugEnabled()) {
getLog().debug("Found ignored versions: "
+ ignoredVersions.stream().map(IgnoreVersion::toString).collect(Collectors.joining(", ")));
}

final List<RemoteRepository> repositories;
if (usePluginRepositories && !useProjectRepositories) {
repositories = mavenSession.getCurrentProject().getRemotePluginRepositories();
} else if (!usePluginRepositories && useProjectRepositories) {
repositories = mavenSession.getCurrentProject().getRemoteProjectRepositories();
} else if (usePluginRepositories) {
repositories = Stream.concat(
mavenSession.getCurrentProject().getRemoteProjectRepositories().stream(),
mavenSession.getCurrentProject().getRemotePluginRepositories().stream())
.distinct()
.collect(Collectors.toList());
} else {
// testing?
repositories = emptyList();
}
return new ArtifactVersions(
artifact,
aetherRepositorySystem
Expand All @@ -191,13 +216,7 @@ public ArtifactVersions lookupArtifactVersions(
.findFirst()
.map(Restriction::toString))
.orElse("(,)")),
usePluginRepositories
? mavenSession
.getCurrentProject()
.getRemotePluginRepositories()
: mavenSession
.getCurrentProject()
.getRemoteProjectRepositories(),
repositories,
"lookupArtifactVersions"))
.getVersions()
.stream()
Expand Down Expand Up @@ -428,16 +447,20 @@ public ArtifactVersion createArtifactVersion(String version) {
return DefaultArtifactVersionCache.of(version);
}

@Override
public Map<Dependency, ArtifactVersions> lookupDependenciesUpdates(
Set<Dependency> dependencies, boolean usePluginRepositories, boolean allowSnapshots)
Set<Dependency> dependencies,
boolean usePluginRepositories,
boolean useProjectRepositories,
boolean allowSnapshots)
throws VersionRetrievalException {
ExecutorService executor = Executors.newFixedThreadPool(LOOKUP_PARALLEL_THREADS);
try {
Map<Dependency, ArtifactVersions> dependencyUpdates = new TreeMap<>(DependencyComparator.INSTANCE);
List<Future<? extends Pair<Dependency, ArtifactVersions>>> futures = dependencies.stream()
.map(dependency -> executor.submit(() -> new ImmutablePair<>(
dependency, lookupDependencyUpdates(dependency, usePluginRepositories, allowSnapshots))))
dependency,
lookupDependencyUpdates(
dependency, usePluginRepositories, useProjectRepositories, allowSnapshots))))
.collect(Collectors.toList());
for (Future<? extends Pair<Dependency, ArtifactVersions>> details : futures) {
Pair<Dependency, ArtifactVersions> pair = details.get();
Expand All @@ -453,12 +476,22 @@ dependency, lookupDependencyUpdates(dependency, usePluginRepositories, allowSnap
}
}

@Override
public Map<Dependency, ArtifactVersions> lookupDependenciesUpdates(
Set<Dependency> dependencies, boolean usePluginRepositories, boolean allowSnapshots)
throws VersionRetrievalException {
return lookupDependenciesUpdates(dependencies, usePluginRepositories, !usePluginRepositories, allowSnapshots);
}

@Override
public ArtifactVersions lookupDependencyUpdates(
Dependency dependency, boolean usePluginRepositories, boolean allowSnapshots)
Dependency dependency,
boolean usePluginRepositories,
boolean useProjectRepositories,
boolean allowSnapshots)
throws VersionRetrievalException {
ArtifactVersions allVersions =
lookupArtifactVersions(createDependencyArtifact(dependency), usePluginRepositories);
ArtifactVersions allVersions = lookupArtifactVersions(
createDependencyArtifact(dependency), null, usePluginRepositories, useProjectRepositories);
return new ArtifactVersions(
allVersions.getArtifact(),
Arrays.stream(allVersions.getAllUpdates(allowSnapshots)).collect(Collectors.toList()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Artifact createDependencyArtifact(
* <b>The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots.</b>
*
* @param artifact The artifact to look for versions of.
* @param usePluginRepositories <code>true</code> will consult the pluginRepositories, while <code>false</code> will
* @param usePluginRepositories {@code true} will consult the pluginRepositories, while {@code false} will
* consult the repositories for normal dependencies.
* @return The details of the available artifact versions.
* @throws VersionRetrievalException thrown if version resolution fails
Expand All @@ -167,7 +167,24 @@ ArtifactVersions lookupArtifactVersions(Artifact artifact, boolean usePluginRepo
* <b>The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots.</b>
*
* @param artifact The artifact to look for versions of.
* @param versionRange versionRange to restrict the search
* @param versionRange versionRange to restrict the search, may be {@code null}
* @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 lookupArtifactVersions(
Artifact artifact, VersionRange versionRange, boolean usePluginRepositories, boolean useProjectRepositories)
throws VersionRetrievalException;

/**
* Looks up the versions of the specified artifact that are available in either the local repository, or the
* appropriate remote repositories.
* <b>The resulting {@link ArtifactVersions} instance will contain all versions, including snapshots.</b>
*
* @param artifact The artifact to look for versions of.
* @param versionRange versionRange to restrict the search, may be {@code null}
* @param usePluginRepositories <code>true</code> will consult the pluginRepositories, while <code>false</code> will
* consult the repositories for normal dependencies.
* @return The details of the available artifact versions.
Expand All @@ -190,18 +207,39 @@ Map<Dependency, ArtifactVersions> lookupDependenciesUpdates(
Set<Dependency> dependencies, boolean usePluginRepositories, boolean allowSnapshots)
throws VersionRetrievalException;

/**
* Returns a map of all possible updates per dependency. The lookup is done in parallel using
* {@code LOOKUP_PARALLEL_THREADS} threads.
*
* @param dependencies The set of {@link Dependency} instances to look up.
* @param usePluginRepositories Search the plugin repositories.
* @param useProjectRepositories whether to use regular project repositories
* @param allowSnapshots whether snapshots should be included
* @return map containing the ArtifactVersions object per dependency
*/
Map<Dependency, ArtifactVersions> lookupDependenciesUpdates(
Set<Dependency> dependencies,
boolean usePluginRepositories,
boolean useProjectRepositories,
boolean allowSnapshots)
throws VersionRetrievalException;

/**
* Creates an {@link org.codehaus.mojo.versions.api.ArtifactVersions} instance from a dependency.
*
* @param dependency The dependency.
* @param usePluginRepositories Search the plugin repositories.
* @param useProjectRepositories whether to use regular project repositories
* @param allowSnapshots whether snapshots should be included
* @return The details of updates to the dependency.
* @throws VersionRetrievalException thrown if version resolution fails
* @since 1.0-beta-1
*/
ArtifactVersions lookupDependencyUpdates(
Dependency dependency, boolean usePluginRepositories, boolean allowSnapshots)
Dependency dependency,
boolean usePluginRepositories,
boolean useProjectRepositories,
boolean allowSnapshots)
throws VersionRetrievalException;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.logging.Log;
Expand Down Expand Up @@ -62,14 +63,26 @@ public Set<Dependency> retainingIn(Collection<Dependency> dependencies) {
return filterBy(dependencies, this::matchersMatch);
}

public Stream<Dependency> retainingIn(Stream<Dependency> inputStream) {
return inputStream.filter(this::matchersMatch);
}

public Set<Dependency> removingFrom(Collection<Dependency> dependencies) {
return filterBy(dependencies, not(this::matchersMatch));
}

private boolean matchersMatch(Dependency dependency) {
public Stream<Dependency> removingFrom(Stream<Dependency> inputStream) {
return inputStream.filter(not(this::matchersMatch));
}

public boolean matchersMatch(Dependency dependency) {
return matchers.stream().anyMatch(m -> m.test(dependency));
}

public boolean matchersDontMatch(Dependency dependency) {
return !matchersMatch(dependency);
}

private TreeSet<Dependency> filterBy(Collection<Dependency> dependencies, Predicate<Dependency> predicate) {
return dependencies.stream()
.filter(predicate)
Expand Down Expand Up @@ -107,6 +120,31 @@ public static Set<Dependency> filterDependencies(
return filtered;
}

/**
* Returns a set of dependencies filtered by the given include- and exclude filters.
* @param dependencies stream of dependencies to filter
* @param includes a list of dependency includes
* @param excludes a list of dependency excludes
* @param section if log is not null, dependency section name for the debug log
* @param log null or log to which debug information will be logged
* @return filtered stream of dependencies
*/
public static Stream<Dependency> filterDependencies(
Stream<Dependency> dependencies, List<String> includes, List<String> excludes, String section, Log log) {
DependencyFilter includeDeps = DependencyFilter.parseFrom(includes);
DependencyFilter excludeDeps = DependencyFilter.parseFrom(excludes);

Stream<Dependency> filtered = includeDeps.retainingIn(dependencies);
filtered = excludeDeps.removingFrom(filtered);

if (log != null && log.isDebugEnabled()) {
log.debug(String.format("parsed includes in %s: %s -> %s", section, includes, includeDeps));
log.debug(String.format("parsed excludes in %s: %s -> %s", section, excludes, excludeDeps));
}

return filtered;
}

private static String output(Collection<Dependency> dependencies) {
return dependencies.stream()
.map(d -> String.format("%s:%s:%s", d.getGroupId(), d.getArtifactId(), d.getVersion()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ public static DependencyBuilder newBuilder() {
* @param artifactId artifactId of the dependency
* @param version version of the dependency
* @return new instance of {@linkplain Dependency}
* @deprecated please use the {@link #newBuilder()} method instead
*/
@Deprecated
public static Dependency dependencyWith(String groupId, String artifactId, String version) {
return newBuilder()
.withGroupId(groupId)
Expand All @@ -154,7 +156,9 @@ public static Dependency dependencyWith(String groupId, String artifactId, Strin
* @param classifier classifier of the dependency
* @param scope scope of the dependency
* @return new instance of {@linkplain Dependency}
* @deprecated please use the {@link #newBuilder()} method instead
*/
@Deprecated
public static Dependency dependencyWith(
String groupId, String artifactId, String version, String type, String classifier, String scope) {
return newBuilder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.codehaus.mojo.versions.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import org.apache.maven.model.Dependency;
import org.apache.maven.model.Extension;
import org.apache.maven.model.InputLocation;

import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;

/**
* Builder class for {@linkplain Extension}
*/
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class ExtensionBuilder {
private Optional<String> groupId = empty();
private Optional<String> artifactId = empty();
private Optional<String> version = empty();
private Map<Object, InputLocation> locations = new HashMap<>();

private ExtensionBuilder() {}

/**
* Passes groupId to the builder
* @param groupId given groupId
* @return builder instance
*/
public ExtensionBuilder withGroupId(String groupId) {
this.groupId = ofNullable(groupId);
return this;
}

/**
* Passes artifactId to the builder
* @param artifactId given artifactId
* @return builder instance
*/
public ExtensionBuilder withArtifactId(String artifactId) {
this.artifactId = ofNullable(artifactId);
return this;
}

/**
* Passes version to the builder
* @param version given version
* @return builder instance
*/
public ExtensionBuilder withVersion(String version) {
this.version = ofNullable(version);
return this;
}

/**
* Passes type to the builder
* @param key location key
* @param location input location
* @return builder instance
*/
public ExtensionBuilder withLocation(Object key, InputLocation location) {
this.locations.put(key, location);
return this;
}

/**
* Creates a new instance of the builder
* @return new instance of the builder
*/
public static ExtensionBuilder newBuilder() {
return new ExtensionBuilder();
}

/**
* Builds the {@linkplain Dependency} instance
* @return {@linkplain Dependency} instance
*/
public Extension build() {
Extension inst = new Extension();
groupId.ifPresent(inst::setGroupId);
artifactId.ifPresent(inst::setArtifactId);
version.ifPresent(inst::setVersion);
locations.forEach(inst::setLocation);
return inst;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
invoker.goals.1 = ${project.groupId}:${project.artifactId}:${project.version}:display-extension-updates
invoker.mavenOpts.1 = -Dversions.outputFile=./output1.txt -DoutputEncoding=UTF-8

invoker.goals.2 = ${project.groupId}:${project.artifactId}:${project.version}:display-extension-updates
invoker.mavenOpts.2 = -Dversions.outputFile=./output2.txt -DoutputEncoding=UTF-8 -DextensionExcludes=localhost

invoker.goals.3 = ${project.groupId}:${project.artifactId}:${project.version}:display-extension-updates
invoker.mavenOpts.3 = -Dversions.outputFile=./output3.txt -DoutputEncoding=UTF-8 -DextensionIncludes=localhost -DextensionExcludes=localhost:dummy-api
Loading

0 comments on commit eca6dbc

Please sign in to comment.