View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.internal.impl.collect.bf;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.io.Closeable;
26  import java.util.ArrayDeque;
27  import java.util.ArrayList;
28  import java.util.Collections;
29  import java.util.LinkedHashMap;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Optional;
33  import java.util.Queue;
34  import java.util.Set;
35  import java.util.concurrent.Callable;
36  import java.util.concurrent.ConcurrentHashMap;
37  import java.util.concurrent.ExecutionException;
38  import java.util.concurrent.ExecutorService;
39  import java.util.concurrent.Future;
40  import java.util.concurrent.TimeUnit;
41  import java.util.concurrent.TimeoutException;
42  import java.util.concurrent.atomic.AtomicReference;
43  import java.util.stream.Collectors;
44  import java.util.stream.Stream;
45  
46  import org.eclipse.aether.RepositorySystemSession;
47  import org.eclipse.aether.RequestTrace;
48  import org.eclipse.aether.artifact.Artifact;
49  import org.eclipse.aether.collection.CollectRequest;
50  import org.eclipse.aether.collection.DependencyCollectionException;
51  import org.eclipse.aether.collection.DependencyManager;
52  import org.eclipse.aether.collection.DependencySelector;
53  import org.eclipse.aether.collection.DependencyTraverser;
54  import org.eclipse.aether.collection.VersionFilter;
55  import org.eclipse.aether.graph.DefaultDependencyNode;
56  import org.eclipse.aether.graph.Dependency;
57  import org.eclipse.aether.graph.DependencyNode;
58  import org.eclipse.aether.impl.ArtifactDescriptorReader;
59  import org.eclipse.aether.impl.RemoteRepositoryManager;
60  import org.eclipse.aether.impl.VersionRangeResolver;
61  import org.eclipse.aether.internal.impl.collect.DataPool;
62  import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollectionContext;
63  import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector;
64  import org.eclipse.aether.internal.impl.collect.DefaultVersionFilterContext;
65  import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate;
66  import org.eclipse.aether.internal.impl.collect.PremanagedDependency;
67  import org.eclipse.aether.repository.RemoteRepository;
68  import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
69  import org.eclipse.aether.resolution.ArtifactDescriptorResult;
70  import org.eclipse.aether.resolution.VersionRangeRequest;
71  import org.eclipse.aether.resolution.VersionRangeResult;
72  import org.eclipse.aether.spi.artifact.decorator.ArtifactDecoratorFactory;
73  import org.eclipse.aether.util.ConfigUtils;
74  import org.eclipse.aether.util.artifact.ArtifactIdUtils;
75  import org.eclipse.aether.util.concurrency.ExecutorUtils;
76  import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
77  import org.eclipse.aether.version.Version;
78  
79  import static org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle.find;
80  
81  /**
82   * Breadth-first {@link org.eclipse.aether.impl.DependencyCollector}
83   *
84   * @since 1.8.0
85   */
86  @Singleton
87  @Named(BfDependencyCollector.NAME)
88  public class BfDependencyCollector extends DependencyCollectorDelegate {
89      public static final String NAME = "bf";
90  
91      private static final String CONFIG_PROPS_PREFIX = DefaultDependencyCollector.CONFIG_PROPS_PREFIX + NAME + ".";
92  
93      /**
94       * The key in the repository session's {@link RepositorySystemSession#getConfigProperties()
95       * configuration properties} used to store a {@link Boolean} flag controlling the resolver's skip mode.
96       *
97       * @since 1.8.0
98       * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
99       * @configurationType {@link java.lang.Boolean}
100      * @configurationDefaultValue {@link #DEFAULT_SKIPPER}
101      */
102     public static final String CONFIG_PROP_SKIPPER = CONFIG_PROPS_PREFIX + "skipper";
103 
104     /**
105      * The default value for {@link #CONFIG_PROP_SKIPPER}, {@code true}.
106      *
107      * @since 1.8.0
108      */
109     public static final boolean DEFAULT_SKIPPER = true;
110 
111     /**
112      * The count of threads to be used when collecting POMs in parallel.
113      *
114      * @since 1.9.0
115      * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
116      * @configurationType {@link java.lang.Integer}
117      * @configurationDefaultValue {@link #DEFAULT_THREADS}
118      */
119     public static final String CONFIG_PROP_THREADS = CONFIG_PROPS_PREFIX + "threads";
120 
121     /**
122      * The default value for {@link #CONFIG_PROP_THREADS}, default value 5.
123      *
124      * @since 1.9.0
125      */
126     public static final int DEFAULT_THREADS = 5;
127 
128     @Inject
129     public BfDependencyCollector(
130             RemoteRepositoryManager remoteRepositoryManager,
131             ArtifactDescriptorReader artifactDescriptorReader,
132             VersionRangeResolver versionRangeResolver,
133             Map<String, ArtifactDecoratorFactory> artifactDecoratorFactories) {
134         super(remoteRepositoryManager, artifactDescriptorReader, versionRangeResolver, artifactDecoratorFactories);
135     }
136 
137     @SuppressWarnings("checkstyle:parameternumber")
138     @Override
139     protected void doCollectDependencies(
140             RepositorySystemSession session,
141             RequestTrace trace,
142             DataPool pool,
143             DefaultDependencyCollectionContext context,
144             DefaultVersionFilterContext versionContext,
145             CollectRequest request,
146             DependencyNode node,
147             List<RemoteRepository> repositories,
148             List<Dependency> dependencies,
149             List<Dependency> managedDependencies,
150             Results results)
151             throws DependencyCollectionException {
152         boolean useSkip = ConfigUtils.getBoolean(session, DEFAULT_SKIPPER, CONFIG_PROP_SKIPPER);
153         int nThreads = ExecutorUtils.threadCount(session, DEFAULT_THREADS, CONFIG_PROP_THREADS);
154         logger.debug("Using thread pool with {} threads to resolve descriptors.", nThreads);
155 
156         if (useSkip) {
157             logger.debug("Collector skip mode enabled");
158         }
159 
160         try (DependencyResolutionSkipper skipper = useSkip
161                         ? DependencyResolutionSkipper.defaultSkipper()
162                         : DependencyResolutionSkipper.neverSkipper();
163                 ParallelDescriptorResolver parallelDescriptorResolver = new ParallelDescriptorResolver(nThreads)) {
164             Args args = new Args(session, pool, context, versionContext, request, skipper, parallelDescriptorResolver);
165 
166             DependencySelector rootDepSelector = session.getDependencySelector() != null
167                     ? session.getDependencySelector().deriveChildSelector(context)
168                     : null;
169             DependencyManager rootDepManager = session.getDependencyManager() != null
170                     ? session.getDependencyManager().deriveChildManager(context)
171                     : null;
172             DependencyTraverser rootDepTraverser = session.getDependencyTraverser() != null
173                     ? session.getDependencyTraverser().deriveChildTraverser(context)
174                     : null;
175             VersionFilter rootVerFilter = session.getVersionFilter() != null
176                     ? session.getVersionFilter().deriveChildFilter(context)
177                     : null;
178 
179             List<DependencyNode> parents = Collections.singletonList(node);
180             for (Dependency dependency : dependencies) {
181                 RequestTrace childTrace =
182                         collectStepTrace(trace, args.request.getRequestContext(), parents, dependency);
183                 DependencyProcessingContext processingContext = new DependencyProcessingContext(
184                         rootDepSelector,
185                         rootDepManager,
186                         rootDepTraverser,
187                         rootVerFilter,
188                         childTrace,
189                         repositories,
190                         managedDependencies,
191                         parents,
192                         dependency,
193                         PremanagedDependency.create(rootDepManager, dependency, false, args.premanagedState));
194                 if (!filter(processingContext)) {
195                     processingContext.withDependency(processingContext.premanagedDependency.getManagedDependency());
196                     resolveArtifactDescriptorAsync(args, processingContext, results);
197                     args.dependencyProcessingQueue.add(processingContext);
198                 }
199             }
200 
201             while (!args.dependencyProcessingQueue.isEmpty()) {
202                 processDependency(
203                         args, results, args.dependencyProcessingQueue.remove(), Collections.emptyList(), false);
204             }
205 
206             if (args.interruptedException.get() != null) {
207                 throw new DependencyCollectionException(
208                         results.getResult(), "Collection interrupted", args.interruptedException.get());
209             }
210         }
211     }
212 
213     @SuppressWarnings("checkstyle:parameternumber")
214     private void processDependency(
215             Args args,
216             Results results,
217             DependencyProcessingContext context,
218             List<Artifact> relocations,
219             boolean disableVersionManagement) {
220         if (Thread.interrupted()) {
221             args.interruptedException.set(new InterruptedException());
222         }
223         if (args.interruptedException.get() != null) {
224             return;
225         }
226         Dependency dependency = context.dependency;
227         PremanagedDependency preManaged = context.premanagedDependency;
228 
229         boolean noDescriptor = isLackingDescriptor(args.session, dependency.getArtifact());
230         boolean traverse =
231                 !noDescriptor && (context.depTraverser == null || context.depTraverser.traverseDependency(dependency));
232 
233         Future<DescriptorResolutionResult> resolutionResultFuture = args.resolver.find(dependency.getArtifact());
234         DescriptorResolutionResult resolutionResult;
235         VersionRangeResult rangeResult;
236         try {
237             resolutionResult = resolutionResultFuture.get();
238             rangeResult = resolutionResult.rangeResult;
239         } catch (Exception e) {
240             results.addException(dependency, e, context.parents);
241             return;
242         }
243 
244         Set<Version> versions = resolutionResult.descriptors.keySet();
245         for (Version version : versions) {
246             Artifact originalArtifact = dependency.getArtifact().setVersion(version.toString());
247             Dependency d = dependency.setArtifact(originalArtifact);
248 
249             final ArtifactDescriptorResult descriptorResult = resolutionResult.descriptors.get(version);
250             if (descriptorResult != null) {
251                 d = d.setArtifact(descriptorResult.getArtifact());
252 
253                 int cycleEntry = find(context.parents, d.getArtifact());
254                 if (cycleEntry >= 0) {
255                     results.addCycle(context.parents, cycleEntry, d);
256                     DependencyNode cycleNode = context.parents.get(cycleEntry);
257                     if (cycleNode.getDependency() != null) {
258                         DefaultDependencyNode child = createDependencyNode(
259                                 relocations, preManaged, rangeResult, version, d, descriptorResult, cycleNode);
260                         context.getParent().getChildren().add(child);
261                         continue;
262                     }
263                 }
264 
265                 if (!descriptorResult.getRelocations().isEmpty()) {
266                     boolean disableVersionManagementSubsequently =
267                             originalArtifact.getGroupId().equals(d.getArtifact().getGroupId())
268                                     && originalArtifact
269                                             .getArtifactId()
270                                             .equals(d.getArtifact().getArtifactId());
271 
272                     PremanagedDependency premanagedDependency = PremanagedDependency.create(
273                             context.depManager, d, disableVersionManagementSubsequently, args.premanagedState);
274                     DependencyProcessingContext relocatedContext = new DependencyProcessingContext(
275                             context.depSelector,
276                             context.depManager,
277                             context.depTraverser,
278                             context.verFilter,
279                             context.trace,
280                             context.repositories,
281                             descriptorResult.getManagedDependencies(),
282                             context.parents,
283                             d,
284                             premanagedDependency);
285 
286                     if (!filter(relocatedContext)) {
287                         relocatedContext.withDependency(premanagedDependency.getManagedDependency());
288                         resolveArtifactDescriptorAsync(args, relocatedContext, results);
289                         processDependency(
290                                 args,
291                                 results,
292                                 relocatedContext,
293                                 descriptorResult.getRelocations(),
294                                 disableVersionManagementSubsequently);
295                     }
296 
297                     return;
298                 } else {
299                     d = args.pool.intern(d.setArtifact(args.pool.intern(d.getArtifact())));
300 
301                     List<RemoteRepository> repos =
302                             getRemoteRepositories(rangeResult.getRepository(version), context.repositories);
303 
304                     DefaultDependencyNode child = createDependencyNode(
305                             relocations,
306                             preManaged,
307                             rangeResult,
308                             version,
309                             d,
310                             descriptorResult.getAliases(),
311                             repos,
312                             args.request.getRequestContext());
313 
314                     context.getParent().getChildren().add(child);
315 
316                     boolean recurse =
317                             traverse && !descriptorResult.getDependencies().isEmpty();
318                     DependencyProcessingContext parentContext = context.withDependency(d);
319                     if (recurse) {
320                         doRecurse(args, parentContext, descriptorResult, child, results, disableVersionManagement);
321                     } else if (!args.skipper.skipResolution(child, parentContext.parents)) {
322                         List<DependencyNode> parents = new ArrayList<>(parentContext.parents.size() + 1);
323                         parents.addAll(parentContext.parents);
324                         parents.add(child);
325                         args.skipper.cache(child, parents);
326                     }
327                 }
328             } else {
329                 List<RemoteRepository> repos =
330                         getRemoteRepositories(rangeResult.getRepository(version), context.repositories);
331                 DefaultDependencyNode child = createDependencyNode(
332                         relocations,
333                         preManaged,
334                         rangeResult,
335                         version,
336                         d,
337                         null,
338                         repos,
339                         args.request.getRequestContext());
340                 context.getParent().getChildren().add(child);
341             }
342         }
343     }
344 
345     @SuppressWarnings("checkstyle:parameternumber")
346     private void doRecurse(
347             Args args,
348             DependencyProcessingContext parentContext,
349             ArtifactDescriptorResult descriptorResult,
350             DefaultDependencyNode child,
351             Results results,
352             boolean disableVersionManagement) {
353         DefaultDependencyCollectionContext context = args.collectionContext.get();
354         args.collectionContext.compareAndSet(
355                 context, context.set(parentContext.dependency, descriptorResult.getManagedDependencies()));
356         context = args.collectionContext.get();
357 
358         DependencySelector childSelector =
359                 parentContext.depSelector != null ? parentContext.depSelector.deriveChildSelector(context) : null;
360         DependencyManager childManager =
361                 parentContext.depManager != null ? parentContext.depManager.deriveChildManager(context) : null;
362         DependencyTraverser childTraverser =
363                 parentContext.depTraverser != null ? parentContext.depTraverser.deriveChildTraverser(context) : null;
364         VersionFilter childFilter =
365                 parentContext.verFilter != null ? parentContext.verFilter.deriveChildFilter(context) : null;
366 
367         final List<RemoteRepository> childRepos = args.ignoreRepos
368                 ? parentContext.repositories
369                 : remoteRepositoryManager.aggregateRepositories(
370                         args.session, parentContext.repositories, descriptorResult.getRepositories(), true);
371 
372         Object key = args.pool.toKey(
373                 parentContext.dependency.getArtifact(),
374                 childRepos,
375                 childSelector,
376                 childManager,
377                 childTraverser,
378                 childFilter);
379 
380         List<DependencyNode> children = args.pool.getChildren(key);
381         if (children == null) {
382             boolean skipResolution = args.skipper.skipResolution(child, parentContext.parents);
383             if (!skipResolution) {
384                 List<DependencyNode> parents = new ArrayList<>(parentContext.parents.size() + 1);
385                 parents.addAll(parentContext.parents);
386                 parents.add(child);
387                 for (Dependency dependency : descriptorResult.getDependencies()) {
388                     RequestTrace childTrace = collectStepTrace(
389                             parentContext.trace, args.request.getRequestContext(), parents, dependency);
390                     PremanagedDependency premanagedDependency = PremanagedDependency.create(
391                             childManager, dependency, disableVersionManagement, args.premanagedState);
392                     DependencyProcessingContext processingContext = new DependencyProcessingContext(
393                             childSelector,
394                             childManager,
395                             childTraverser,
396                             childFilter,
397                             childTrace,
398                             childRepos,
399                             descriptorResult.getManagedDependencies(),
400                             parents,
401                             dependency,
402                             premanagedDependency);
403                     if (!filter(processingContext)) {
404                         // resolve descriptors ahead for managed dependency
405                         processingContext.withDependency(processingContext.premanagedDependency.getManagedDependency());
406                         resolveArtifactDescriptorAsync(args, processingContext, results);
407                         args.dependencyProcessingQueue.add(processingContext);
408                     }
409                 }
410                 args.pool.putChildren(key, child.getChildren());
411                 args.skipper.cache(child, parents);
412             }
413         } else {
414             child.setChildren(children);
415         }
416     }
417 
418     private boolean filter(DependencyProcessingContext context) {
419         return context.depSelector != null && !context.depSelector.selectDependency(context.dependency);
420     }
421 
422     private void resolveArtifactDescriptorAsync(Args args, DependencyProcessingContext context, Results results) {
423         Dependency dependency = context.dependency;
424         args.resolver.resolveDescriptors(dependency.getArtifact(), () -> {
425             VersionRangeRequest rangeRequest = createVersionRangeRequest(
426                     args.request.getRequestContext(), context.trace, context.repositories, dependency);
427             VersionRangeResult rangeResult = cachedResolveRangeResult(rangeRequest, args.pool, args.session);
428             List<? extends Version> versions =
429                     filterVersions(dependency, rangeResult, context.verFilter, args.versionContext);
430 
431             // resolve newer version first to maximize benefits of skipper
432             Collections.reverse(versions);
433 
434             Map<Version, ArtifactDescriptorResult> descriptors = new ConcurrentHashMap<>(versions.size());
435             Stream<? extends Version> stream = versions.size() > 1 ? versions.parallelStream() : versions.stream();
436             stream.forEach(version -> Optional.ofNullable(
437                             resolveDescriptorForVersion(args, context, results, dependency, version))
438                     .ifPresent(r -> descriptors.put(version, r)));
439 
440             DescriptorResolutionResult resolutionResult =
441                     new DescriptorResolutionResult(dependency.getArtifact(), rangeResult);
442             // keep original sequence
443             versions.forEach(version -> resolutionResult.descriptors.put(version, descriptors.get(version)));
444             // populate for versions in version range
445             resolutionResult.flatten().forEach(dr -> args.resolver.cacheVersionRangeDescriptor(dr.artifact, dr));
446 
447             return resolutionResult;
448         });
449     }
450 
451     private ArtifactDescriptorResult resolveDescriptorForVersion(
452             Args args, DependencyProcessingContext context, Results results, Dependency dependency, Version version) {
453         Artifact original = dependency.getArtifact();
454         Artifact newArtifact = original.setVersion(version.toString());
455         Dependency newDependency =
456                 new Dependency(newArtifact, dependency.getScope(), dependency.isOptional(), dependency.getExclusions());
457         DependencyProcessingContext newContext = context.copy();
458 
459         ArtifactDescriptorRequest descriptorRequest = createArtifactDescriptorRequest(
460                 args.request.getRequestContext(), context.trace, newContext.repositories, newDependency);
461         return isLackingDescriptor(args.session, newArtifact)
462                 ? new ArtifactDescriptorResult(descriptorRequest)
463                 : resolveCachedArtifactDescriptor(
464                         args.pool,
465                         descriptorRequest,
466                         args.session,
467                         newContext.withDependency(newDependency).dependency,
468                         results,
469                         context.parents);
470     }
471 
472     static class ParallelDescriptorResolver implements Closeable {
473         private final ExecutorService executorService;
474 
475         /**
476          * Artifact ID -> Future of DescriptorResolutionResult
477          */
478         private final Map<String, Future<DescriptorResolutionResult>> results = new ConcurrentHashMap<>(256);
479 
480         ParallelDescriptorResolver(int threads) {
481             this.executorService = ExecutorUtils.threadPool(threads, getClass().getSimpleName() + "-");
482         }
483 
484         void resolveDescriptors(Artifact artifact, Callable<DescriptorResolutionResult> callable) {
485             results.computeIfAbsent(ArtifactIdUtils.toId(artifact), key -> this.executorService.submit(callable));
486         }
487 
488         void cacheVersionRangeDescriptor(Artifact artifact, DescriptorResolutionResult resolutionResult) {
489             results.computeIfAbsent(ArtifactIdUtils.toId(artifact), key -> new DoneFuture<>(resolutionResult));
490         }
491 
492         Future<DescriptorResolutionResult> find(Artifact artifact) {
493             return results.get(ArtifactIdUtils.toId(artifact));
494         }
495 
496         @Override
497         public void close() {
498             executorService.shutdown();
499         }
500     }
501 
502     static class DoneFuture<V> implements Future<V> {
503         private final V v;
504 
505         DoneFuture(V v) {
506             this.v = v;
507         }
508 
509         @Override
510         public boolean cancel(boolean mayInterruptIfRunning) {
511             return false;
512         }
513 
514         @Override
515         public boolean isCancelled() {
516             return false;
517         }
518 
519         @Override
520         public boolean isDone() {
521             return true;
522         }
523 
524         @Override
525         public V get() throws InterruptedException, ExecutionException {
526             return v;
527         }
528 
529         @Override
530         public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
531             return v;
532         }
533     }
534 
535     static class DescriptorResolutionResult {
536         Artifact artifact;
537 
538         VersionRangeResult rangeResult;
539 
540         Map<Version, ArtifactDescriptorResult> descriptors;
541 
542         DescriptorResolutionResult(Artifact artifact, VersionRangeResult rangeResult) {
543             this.artifact = artifact;
544             this.rangeResult = rangeResult;
545             this.descriptors = new LinkedHashMap<>(rangeResult.getVersions().size());
546         }
547 
548         DescriptorResolutionResult(
549                 VersionRangeResult rangeResult, Version version, ArtifactDescriptorResult descriptor) {
550             // NOTE: In case of A1 -> A2 relocation this happens:
551             // ArtifactDescriptorResult read by ArtifactDescriptorResultReader for A1
552             // will return instance that will have artifact = A2 (as RelocatedArtifact).
553             // So to properly "key" this instance, we need to use "originally requested" A1 instead!
554             // In short:
555             // ArtifactDescriptorRequest.artifact != ArtifactDescriptorResult.artifact WHEN relocation in play
556             // otherwise (no relocation), they are EQUAL.
557             this(descriptor.getRequest().getArtifact(), rangeResult);
558             this.descriptors.put(version, descriptor);
559         }
560 
561         List<DescriptorResolutionResult> flatten() {
562             if (descriptors.size() > 1) {
563                 return descriptors.entrySet().stream()
564                         .map(e -> new DescriptorResolutionResult(rangeResult, e.getKey(), e.getValue()))
565                         .collect(Collectors.toList());
566             } else {
567                 return Collections.emptyList();
568             }
569         }
570     }
571 
572     static class Args {
573 
574         final RepositorySystemSession session;
575 
576         final boolean ignoreRepos;
577 
578         final boolean premanagedState;
579 
580         final DataPool pool;
581 
582         final Queue<DependencyProcessingContext> dependencyProcessingQueue = new ArrayDeque<>(128);
583 
584         final AtomicReference<DefaultDependencyCollectionContext> collectionContext;
585 
586         final DefaultVersionFilterContext versionContext;
587 
588         final CollectRequest request;
589 
590         final DependencyResolutionSkipper skipper;
591 
592         final ParallelDescriptorResolver resolver;
593 
594         final AtomicReference<InterruptedException> interruptedException;
595 
596         Args(
597                 RepositorySystemSession session,
598                 DataPool pool,
599                 DefaultDependencyCollectionContext collectionContext,
600                 DefaultVersionFilterContext versionContext,
601                 CollectRequest request,
602                 DependencyResolutionSkipper skipper,
603                 ParallelDescriptorResolver resolver) {
604             this.session = session;
605             this.request = request;
606             this.ignoreRepos = session.isIgnoreArtifactDescriptorRepositories();
607             this.premanagedState = ConfigUtils.getBoolean(session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE);
608             this.pool = pool;
609             this.collectionContext = new AtomicReference<>(collectionContext);
610             this.versionContext = versionContext;
611             this.skipper = skipper;
612             this.resolver = resolver;
613             this.interruptedException = new AtomicReference<>(null);
614         }
615     }
616 }