shaded.org.eclipse.aether.internal.impl.collect.bf.BfDependencyCollector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-cloud-contract-shade Show documentation
Show all versions of spring-cloud-contract-shade Show documentation
Spring Cloud Contract Shaded Dependencies
The newest version!
/*
* 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 shaded.shaded.org.eclipse.aether.internal.impl.collect.bf;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.Closeable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.RequestTrace;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.ArtifactType;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.DependencyManager;
import org.eclipse.aether.collection.DependencySelector;
import org.eclipse.aether.collection.DependencyTraverser;
import org.eclipse.aether.collection.VersionFilter;
import org.eclipse.aether.graph.DefaultDependencyNode;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
import shaded.shaded.org.eclipse.aether.impl.ArtifactDescriptorReader;
import shaded.shaded.org.eclipse.aether.impl.RemoteRepositoryManager;
import shaded.shaded.org.eclipse.aether.impl.VersionRangeResolver;
import shaded.shaded.org.eclipse.aether.internal.impl.collect.DataPool;
import shaded.shaded.org.eclipse.aether.internal.impl.collect.DefaultDependencyCollectionContext;
import shaded.shaded.org.eclipse.aether.internal.impl.collect.DefaultVersionFilterContext;
import shaded.shaded.org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate;
import shaded.shaded.org.eclipse.aether.internal.impl.collect.PremanagedDependency;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorException;
import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
import org.eclipse.aether.resolution.ArtifactDescriptorResult;
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResult;
import shaded.shaded.org.eclipse.aether.spi.locator.Service;
import org.eclipse.aether.util.ConfigUtils;
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
import org.eclipse.aether.util.concurrency.ExecutorUtils;
import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
import org.eclipse.aether.version.Version;
import static shaded.shaded.org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle.find;
/**
* Breadth-first {@link shaded.shaded.org.eclipse.aether.impl.DependencyCollector}
*
* @since 1.8.0
*/
@Singleton
@Named(BfDependencyCollector.NAME)
public class BfDependencyCollector extends DependencyCollectorDelegate implements Service {
public static final String NAME = "bf";
/**
* The key in the repository session's {@link RepositorySystemSession#getConfigProperties()
* configuration properties} used to store a {@link Boolean} flag controlling the resolver's skip mode.
*
* @since 1.8.0
*/
static final String CONFIG_PROP_SKIPPER = "aether.dependencyCollector.bf.skipper";
/**
* The default value for {@link #CONFIG_PROP_SKIPPER}, {@code true}.
*
* @since 1.8.0
*/
static final boolean CONFIG_PROP_SKIPPER_DEFAULT = true;
/**
* The count of threads to be used when collecting POMs in parallel, default value 5.
*
* @since 1.9.0
*/
static final String CONFIG_PROP_THREADS = "aether.dependencyCollector.bf.threads";
/**
* Default ctor for SL.
*
* @deprecated Will be dropped once SL gone.
*/
@Deprecated
public BfDependencyCollector() {
// enables default constructor
}
@Inject
public BfDependencyCollector(
RemoteRepositoryManager remoteRepositoryManager,
ArtifactDescriptorReader artifactDescriptorReader,
VersionRangeResolver versionRangeResolver) {
super(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver);
}
@SuppressWarnings("checkstyle:parameternumber")
@Override
protected void doCollectDependencies(
RepositorySystemSession session,
RequestTrace trace,
DataPool pool,
DefaultDependencyCollectionContext context,
DefaultVersionFilterContext versionContext,
CollectRequest request,
DependencyNode node,
List repositories,
List dependencies,
List managedDependencies,
Results results) {
boolean useSkip = ConfigUtils.getBoolean(session, CONFIG_PROP_SKIPPER_DEFAULT, CONFIG_PROP_SKIPPER);
int nThreads = ExecutorUtils.threadCount(session, 5, CONFIG_PROP_THREADS, "maven.artifact.threads");
logger.debug("Using thread pool with {} threads to resolve descriptors.", nThreads);
if (useSkip) {
logger.debug("Collector skip mode enabled");
}
try (DependencyResolutionSkipper skipper = useSkip
? DependencyResolutionSkipper.defaultSkipper()
: DependencyResolutionSkipper.neverSkipper();
ParallelDescriptorResolver parallelDescriptorResolver = new ParallelDescriptorResolver(nThreads)) {
Args args = new Args(session, pool, context, versionContext, request, skipper, parallelDescriptorResolver);
DependencySelector rootDepSelector = session.getDependencySelector() != null
? session.getDependencySelector().deriveChildSelector(context)
: null;
DependencyManager rootDepManager = session.getDependencyManager() != null
? session.getDependencyManager().deriveChildManager(context)
: null;
DependencyTraverser rootDepTraverser = session.getDependencyTraverser() != null
? session.getDependencyTraverser().deriveChildTraverser(context)
: null;
VersionFilter rootVerFilter = session.getVersionFilter() != null
? session.getVersionFilter().deriveChildFilter(context)
: null;
List parents = Collections.singletonList(node);
for (Dependency dependency : dependencies) {
RequestTrace childTrace =
collectStepTrace(trace, args.request.getRequestContext(), parents, dependency);
DependencyProcessingContext processingContext = new DependencyProcessingContext(
rootDepSelector,
rootDepManager,
rootDepTraverser,
rootVerFilter,
childTrace,
repositories,
managedDependencies,
parents,
dependency,
PremanagedDependency.create(rootDepManager, dependency, false, args.premanagedState));
if (!filter(processingContext)) {
processingContext.withDependency(processingContext.premanagedDependency.getManagedDependency());
resolveArtifactDescriptorAsync(args, processingContext, results);
args.dependencyProcessingQueue.add(processingContext);
}
}
while (!args.dependencyProcessingQueue.isEmpty()) {
processDependency(
args, results, args.dependencyProcessingQueue.remove(), Collections.emptyList(), false);
}
}
}
@SuppressWarnings("checkstyle:parameternumber")
private void processDependency(
Args args,
Results results,
DependencyProcessingContext context,
List relocations,
boolean disableVersionManagement) {
Dependency dependency = context.dependency;
PremanagedDependency preManaged = context.premanagedDependency;
boolean noDescriptor = isLackingDescriptor(dependency.getArtifact());
boolean traverse =
!noDescriptor && (context.depTraverser == null || context.depTraverser.traverseDependency(dependency));
Future resolutionResultFuture = args.resolver.find(dependency.getArtifact());
DescriptorResolutionResult resolutionResult;
VersionRangeResult rangeResult;
try {
resolutionResult = resolutionResultFuture.get();
rangeResult = resolutionResult.rangeResult;
} catch (Exception e) {
results.addException(dependency, e, context.parents);
return;
}
Set versions = resolutionResult.descriptors.keySet();
for (Version version : versions) {
Artifact originalArtifact = dependency.getArtifact().setVersion(version.toString());
Dependency d = dependency.setArtifact(originalArtifact);
final ArtifactDescriptorResult descriptorResult = resolutionResult.descriptors.get(version);
if (descriptorResult != null) {
d = d.setArtifact(descriptorResult.getArtifact());
int cycleEntry = find(context.parents, d.getArtifact());
if (cycleEntry >= 0) {
results.addCycle(context.parents, cycleEntry, d);
DependencyNode cycleNode = context.parents.get(cycleEntry);
if (cycleNode.getDependency() != null) {
DefaultDependencyNode child = createDependencyNode(
relocations, preManaged, rangeResult, version, d, descriptorResult, cycleNode);
context.getParent().getChildren().add(child);
continue;
}
}
if (!descriptorResult.getRelocations().isEmpty()) {
boolean disableVersionManagementSubsequently =
originalArtifact.getGroupId().equals(d.getArtifact().getGroupId())
&& originalArtifact
.getArtifactId()
.equals(d.getArtifact().getArtifactId());
PremanagedDependency premanagedDependency = PremanagedDependency.create(
context.depManager, d, disableVersionManagementSubsequently, args.premanagedState);
DependencyProcessingContext relocatedContext = new DependencyProcessingContext(
context.depSelector,
context.depManager,
context.depTraverser,
context.verFilter,
context.trace,
context.repositories,
descriptorResult.getManagedDependencies(),
context.parents,
d,
premanagedDependency);
if (!filter(relocatedContext)) {
relocatedContext.withDependency(premanagedDependency.getManagedDependency());
resolveArtifactDescriptorAsync(args, relocatedContext, results);
processDependency(
args,
results,
relocatedContext,
descriptorResult.getRelocations(),
disableVersionManagementSubsequently);
}
return;
} else {
d = args.pool.intern(d.setArtifact(args.pool.intern(d.getArtifact())));
List repos =
getRemoteRepositories(rangeResult.getRepository(version), context.repositories);
DefaultDependencyNode child = createDependencyNode(
relocations,
preManaged,
rangeResult,
version,
d,
descriptorResult.getAliases(),
repos,
args.request.getRequestContext());
context.getParent().getChildren().add(child);
boolean recurse =
traverse && !descriptorResult.getDependencies().isEmpty();
DependencyProcessingContext parentContext = context.withDependency(d);
if (recurse) {
doRecurse(args, parentContext, descriptorResult, child, results, disableVersionManagement);
} else if (!args.skipper.skipResolution(child, parentContext.parents)) {
List parents = new ArrayList<>(parentContext.parents.size() + 1);
parents.addAll(parentContext.parents);
parents.add(child);
args.skipper.cache(child, parents);
}
}
} else {
List repos =
getRemoteRepositories(rangeResult.getRepository(version), context.repositories);
DefaultDependencyNode child = createDependencyNode(
relocations,
preManaged,
rangeResult,
version,
d,
null,
repos,
args.request.getRequestContext());
context.getParent().getChildren().add(child);
}
}
}
@SuppressWarnings("checkstyle:parameternumber")
private void doRecurse(
Args args,
DependencyProcessingContext parentContext,
ArtifactDescriptorResult descriptorResult,
DefaultDependencyNode child,
Results results,
boolean disableVersionManagement) {
DefaultDependencyCollectionContext context = args.collectionContext;
context.set(parentContext.dependency, descriptorResult.getManagedDependencies());
DependencySelector childSelector =
parentContext.depSelector != null ? parentContext.depSelector.deriveChildSelector(context) : null;
DependencyManager childManager =
parentContext.depManager != null ? parentContext.depManager.deriveChildManager(context) : null;
DependencyTraverser childTraverser =
parentContext.depTraverser != null ? parentContext.depTraverser.deriveChildTraverser(context) : null;
VersionFilter childFilter =
parentContext.verFilter != null ? parentContext.verFilter.deriveChildFilter(context) : null;
final List childRepos = args.ignoreRepos
? parentContext.repositories
: remoteRepositoryManager.aggregateRepositories(
args.session, parentContext.repositories, descriptorResult.getRepositories(), true);
Object key = args.pool.toKey(
parentContext.dependency.getArtifact(),
childRepos,
childSelector,
childManager,
childTraverser,
childFilter);
List children = args.pool.getChildren(key);
if (children == null) {
boolean skipResolution = args.skipper.skipResolution(child, parentContext.parents);
if (!skipResolution) {
List parents = new ArrayList<>(parentContext.parents.size() + 1);
parents.addAll(parentContext.parents);
parents.add(child);
for (Dependency dependency : descriptorResult.getDependencies()) {
RequestTrace childTrace = collectStepTrace(
parentContext.trace, args.request.getRequestContext(), parents, dependency);
PremanagedDependency premanagedDependency = PremanagedDependency.create(
childManager, dependency, disableVersionManagement, args.premanagedState);
DependencyProcessingContext processingContext = new DependencyProcessingContext(
childSelector,
childManager,
childTraverser,
childFilter,
childTrace,
childRepos,
descriptorResult.getManagedDependencies(),
parents,
dependency,
premanagedDependency);
if (!filter(processingContext)) {
// resolve descriptors ahead for managed dependency
processingContext.withDependency(processingContext.premanagedDependency.getManagedDependency());
resolveArtifactDescriptorAsync(args, processingContext, results);
args.dependencyProcessingQueue.add(processingContext);
}
}
args.pool.putChildren(key, child.getChildren());
args.skipper.cache(child, parents);
}
} else {
child.setChildren(children);
}
}
private boolean filter(DependencyProcessingContext context) {
return context.depSelector != null && !context.depSelector.selectDependency(context.dependency);
}
private void resolveArtifactDescriptorAsync(Args args, DependencyProcessingContext context, Results results) {
Dependency dependency = context.dependency;
args.resolver.resolveDescriptors(dependency.getArtifact(), () -> {
VersionRangeRequest rangeRequest = createVersionRangeRequest(
args.request.getRequestContext(), context.trace, context.repositories, dependency);
VersionRangeResult rangeResult = cachedResolveRangeResult(rangeRequest, args.pool, args.session);
List versions =
filterVersions(dependency, rangeResult, context.verFilter, args.versionContext);
// resolve newer version first to maximize benefits of skipper
Collections.reverse(versions);
Map descriptors = new ConcurrentHashMap<>(versions.size());
Stream stream = versions.size() > 1 ? versions.parallelStream() : versions.stream();
stream.forEach(version -> Optional.ofNullable(
resolveDescriptorForVersion(args, context, results, dependency, version))
.ifPresent(r -> descriptors.put(version, r)));
DescriptorResolutionResult resolutionResult =
new DescriptorResolutionResult(dependency.getArtifact(), rangeResult);
// keep original sequence
versions.forEach(version -> resolutionResult.descriptors.put(version, descriptors.get(version)));
// populate for versions in version range
resolutionResult.flatten().forEach(dr -> args.resolver.cacheVersionRangeDescriptor(dr.artifact, dr));
return resolutionResult;
});
}
private ArtifactDescriptorResult resolveDescriptorForVersion(
Args args, DependencyProcessingContext context, Results results, Dependency dependency, Version version) {
Artifact original = dependency.getArtifact();
Artifact newArtifact = new DefaultArtifact(
original.getGroupId(),
original.getArtifactId(),
original.getClassifier(),
original.getExtension(),
version.toString(),
original.getProperties(),
(ArtifactType) null);
Dependency newDependency =
new Dependency(newArtifact, dependency.getScope(), dependency.isOptional(), dependency.getExclusions());
DependencyProcessingContext newContext = context.copy();
ArtifactDescriptorRequest descriptorRequest = createArtifactDescriptorRequest(
args.request.getRequestContext(), context.trace, newContext.repositories, newDependency);
return isLackingDescriptor(newArtifact)
? new ArtifactDescriptorResult(descriptorRequest)
: resolveCachedArtifactDescriptor(
args.pool, descriptorRequest, args.session, newContext.withDependency(newDependency), results);
}
private ArtifactDescriptorResult resolveCachedArtifactDescriptor(
DataPool pool,
ArtifactDescriptorRequest descriptorRequest,
RepositorySystemSession session,
DependencyProcessingContext context,
Results results) {
Object key = pool.toKey(descriptorRequest);
ArtifactDescriptorResult descriptorResult = pool.getDescriptor(key, descriptorRequest);
if (descriptorResult == null) {
try {
descriptorResult = descriptorReader.readArtifactDescriptor(session, descriptorRequest);
pool.putDescriptor(key, descriptorResult);
} catch (ArtifactDescriptorException e) {
results.addException(context.dependency, e, context.parents);
pool.putDescriptor(key, e);
return null;
}
} else if (descriptorResult == DataPool.NO_DESCRIPTOR) {
return null;
}
return descriptorResult;
}
static class ParallelDescriptorResolver implements Closeable {
private final ExecutorService executorService;
/**
* Artifact ID -> Future of DescriptorResolutionResult
*/
private final Map> results = new ConcurrentHashMap<>(256);
ParallelDescriptorResolver(int threads) {
this.executorService = ExecutorUtils.threadPool(threads, getClass().getSimpleName() + "-");
}
void resolveDescriptors(Artifact artifact, Callable callable) {
results.computeIfAbsent(ArtifactIdUtils.toId(artifact), key -> this.executorService.submit(callable));
}
void cacheVersionRangeDescriptor(Artifact artifact, DescriptorResolutionResult resolutionResult) {
results.computeIfAbsent(ArtifactIdUtils.toId(artifact), key -> new DoneFuture<>(resolutionResult));
}
Future find(Artifact artifact) {
return results.get(ArtifactIdUtils.toId(artifact));
}
@Override
public void close() {
executorService.shutdown();
}
}
static class DoneFuture implements Future {
private final V v;
DoneFuture(V v) {
this.v = v;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return true;
}
@Override
public V get() throws InterruptedException, ExecutionException {
return v;
}
@Override
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return v;
}
}
static class DescriptorResolutionResult {
Artifact artifact;
VersionRangeResult rangeResult;
Map descriptors;
DescriptorResolutionResult(Artifact artifact, VersionRangeResult rangeResult) {
this.artifact = artifact;
this.rangeResult = rangeResult;
this.descriptors = new LinkedHashMap<>(rangeResult.getVersions().size());
}
DescriptorResolutionResult(
VersionRangeResult rangeResult, Version version, ArtifactDescriptorResult descriptor) {
// NOTE: In case of A1 -> A2 relocation this happens:
// ArtifactDescriptorResult read by ArtifactDescriptorResultReader for A1
// will return instance that will have artifact = A2 (as RelocatedArtifact).
// So to properly "key" this instance, we need to use "originally requested" A1 instead!
// In short:
// ArtifactDescriptorRequest.artifact != ArtifactDescriptorResult.artifact WHEN relocation in play
// otherwise (no relocation), they are EQUAL.
this(descriptor.getRequest().getArtifact(), rangeResult);
this.descriptors.put(version, descriptor);
}
List flatten() {
if (descriptors.size() > 1) {
return descriptors.entrySet().stream()
.map(e -> new DescriptorResolutionResult(rangeResult, e.getKey(), e.getValue()))
.collect(Collectors.toList());
} else {
return Collections.emptyList();
}
}
}
static class Args {
final RepositorySystemSession session;
final boolean ignoreRepos;
final boolean premanagedState;
final DataPool pool;
final Queue dependencyProcessingQueue = new ArrayDeque<>(128);
final DefaultDependencyCollectionContext collectionContext;
final DefaultVersionFilterContext versionContext;
final CollectRequest request;
final DependencyResolutionSkipper skipper;
final ParallelDescriptorResolver resolver;
Args(
RepositorySystemSession session,
DataPool pool,
DefaultDependencyCollectionContext collectionContext,
DefaultVersionFilterContext versionContext,
CollectRequest request,
DependencyResolutionSkipper skipper,
ParallelDescriptorResolver resolver) {
this.session = session;
this.request = request;
this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories();
this.premanagedState = ConfigUtils.getBoolean(session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE);
this.pool = pool;
this.collectionContext = collectionContext;
this.versionContext = versionContext;
this.skipper = skipper;
this.resolver = resolver;
}
}
}