1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.IOException;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.nio.file.attribute.FileTime;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.concurrent.atomic.AtomicBoolean;
37
38 import org.eclipse.aether.ConfigurationProperties;
39 import org.eclipse.aether.RepositoryEvent;
40 import org.eclipse.aether.RepositoryEvent.EventType;
41 import org.eclipse.aether.RepositorySystemSession;
42 import org.eclipse.aether.RequestTrace;
43 import org.eclipse.aether.SyncContext;
44 import org.eclipse.aether.artifact.Artifact;
45 import org.eclipse.aether.impl.ArtifactResolver;
46 import org.eclipse.aether.impl.OfflineController;
47 import org.eclipse.aether.impl.RemoteRepositoryFilterManager;
48 import org.eclipse.aether.impl.RemoteRepositoryManager;
49 import org.eclipse.aether.impl.RepositoryConnectorProvider;
50 import org.eclipse.aether.impl.RepositoryEventDispatcher;
51 import org.eclipse.aether.impl.UpdateCheck;
52 import org.eclipse.aether.impl.UpdateCheckManager;
53 import org.eclipse.aether.impl.VersionResolver;
54 import org.eclipse.aether.repository.*;
55 import org.eclipse.aether.resolution.ArtifactRequest;
56 import org.eclipse.aether.resolution.ArtifactResolutionException;
57 import org.eclipse.aether.resolution.ArtifactResult;
58 import org.eclipse.aether.resolution.ResolutionErrorPolicy;
59 import org.eclipse.aether.resolution.VersionRequest;
60 import org.eclipse.aether.resolution.VersionResolutionException;
61 import org.eclipse.aether.resolution.VersionResult;
62 import org.eclipse.aether.scope.SystemDependencyScope;
63 import org.eclipse.aether.spi.connector.ArtifactDownload;
64 import org.eclipse.aether.spi.connector.RepositoryConnector;
65 import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter;
66 import org.eclipse.aether.spi.io.PathProcessor;
67 import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor;
68 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
69 import org.eclipse.aether.transfer.ArtifactFilteredOutException;
70 import org.eclipse.aether.transfer.ArtifactNotFoundException;
71 import org.eclipse.aether.transfer.ArtifactTransferException;
72 import org.eclipse.aether.transfer.NoRepositoryConnectorException;
73 import org.eclipse.aether.transfer.RepositoryOfflineException;
74 import org.eclipse.aether.util.ConfigUtils;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78 import static java.util.Objects.requireNonNull;
79
80
81
82
83 @Singleton
84 @Named
85 public class DefaultArtifactResolver implements ArtifactResolver {
86
87 public static final String CONFIG_PROPS_PREFIX = ConfigurationProperties.PREFIX_AETHER + "artifactResolver.";
88
89
90
91
92
93
94
95
96
97
98
99 public static final String CONFIG_PROP_SNAPSHOT_NORMALIZATION = CONFIG_PROPS_PREFIX + "snapshotNormalization";
100
101 public static final boolean DEFAULT_SNAPSHOT_NORMALIZATION = true;
102
103
104
105
106
107
108
109
110
111 public static final String CONFIG_PROP_SIMPLE_LRM_INTEROP = CONFIG_PROPS_PREFIX + "simpleLrmInterop";
112
113 public static final boolean DEFAULT_SIMPLE_LRM_INTEROP = false;
114
115 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultArtifactResolver.class);
116
117 private final PathProcessor pathProcessor;
118
119 private final RepositoryEventDispatcher repositoryEventDispatcher;
120
121 private final VersionResolver versionResolver;
122
123 private final UpdateCheckManager updateCheckManager;
124
125 private final RepositoryConnectorProvider repositoryConnectorProvider;
126
127 private final RemoteRepositoryManager remoteRepositoryManager;
128
129 private final SyncContextFactory syncContextFactory;
130
131 private final OfflineController offlineController;
132
133 private final Map<String, ArtifactResolverPostProcessor> artifactResolverPostProcessors;
134
135 private final RemoteRepositoryFilterManager remoteRepositoryFilterManager;
136
137 @SuppressWarnings("checkstyle:parameternumber")
138 @Inject
139 public DefaultArtifactResolver(
140 PathProcessor pathProcessor,
141 RepositoryEventDispatcher repositoryEventDispatcher,
142 VersionResolver versionResolver,
143 UpdateCheckManager updateCheckManager,
144 RepositoryConnectorProvider repositoryConnectorProvider,
145 RemoteRepositoryManager remoteRepositoryManager,
146 SyncContextFactory syncContextFactory,
147 OfflineController offlineController,
148 Map<String, ArtifactResolverPostProcessor> artifactResolverPostProcessors,
149 RemoteRepositoryFilterManager remoteRepositoryFilterManager) {
150 this.pathProcessor = requireNonNull(pathProcessor, "path processor cannot be null");
151 this.repositoryEventDispatcher =
152 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null");
153 this.versionResolver = requireNonNull(versionResolver, "version resolver cannot be null");
154 this.updateCheckManager = requireNonNull(updateCheckManager, "update check manager cannot be null");
155 this.repositoryConnectorProvider =
156 requireNonNull(repositoryConnectorProvider, "repository connector provider cannot be null");
157 this.remoteRepositoryManager =
158 requireNonNull(remoteRepositoryManager, "remote repository provider cannot be null");
159 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null");
160 this.offlineController = requireNonNull(offlineController, "offline controller cannot be null");
161 this.artifactResolverPostProcessors =
162 requireNonNull(artifactResolverPostProcessors, "artifact resolver post-processors cannot be null");
163 this.remoteRepositoryFilterManager =
164 requireNonNull(remoteRepositoryFilterManager, "remote repository filter manager cannot be null");
165 }
166
167 @Override
168 public ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request)
169 throws ArtifactResolutionException {
170 requireNonNull(session, "session cannot be null");
171 requireNonNull(request, "request cannot be null");
172
173 return resolveArtifacts(session, Collections.singleton(request)).get(0);
174 }
175
176 @Override
177 public List<ArtifactResult> resolveArtifacts(
178 RepositorySystemSession session, Collection<? extends ArtifactRequest> requests)
179 throws ArtifactResolutionException {
180 requireNonNull(session, "session cannot be null");
181 requireNonNull(requests, "requests cannot be null");
182 try (SyncContext shared = syncContextFactory.newInstance(session, true);
183 SyncContext exclusive = syncContextFactory.newInstance(session, false)) {
184 Collection<Artifact> artifacts = new ArrayList<>(requests.size());
185 SystemDependencyScope systemDependencyScope = session.getSystemDependencyScope();
186 for (ArtifactRequest request : requests) {
187 if (systemDependencyScope != null
188 && systemDependencyScope.getSystemPath(request.getArtifact()) != null) {
189 continue;
190 }
191 artifacts.add(request.getArtifact());
192 }
193
194 return resolve(shared, exclusive, artifacts, session, requests);
195 }
196 }
197
198 @SuppressWarnings("checkstyle:methodlength")
199 private List<ArtifactResult> resolve(
200 SyncContext shared,
201 SyncContext exclusive,
202 Collection<Artifact> subjects,
203 RepositorySystemSession session,
204 Collection<? extends ArtifactRequest> requests)
205 throws ArtifactResolutionException {
206 SystemDependencyScope systemDependencyScope = session.getSystemDependencyScope();
207 SyncContext current = shared;
208 try {
209 while (true) {
210 current.acquire(subjects, null);
211
212 boolean failures = false;
213 final List<ArtifactResult> results = new ArrayList<>(requests.size());
214 final boolean simpleLrmInterop =
215 ConfigUtils.getBoolean(session, DEFAULT_SIMPLE_LRM_INTEROP, CONFIG_PROP_SIMPLE_LRM_INTEROP);
216 final LocalRepositoryManager lrm = session.getLocalRepositoryManager();
217 final WorkspaceReader workspace = session.getWorkspaceReader();
218 final List<ResolutionGroup> groups = new ArrayList<>();
219
220 final RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session);
221
222 for (ArtifactRequest request : requests) {
223 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
224
225 ArtifactResult result = new ArtifactResult(request);
226 results.add(result);
227
228 Artifact artifact = request.getArtifact();
229
230 if (current == shared) {
231 artifactResolving(session, trace, artifact);
232 }
233
234 String localPath =
235 systemDependencyScope != null ? systemDependencyScope.getSystemPath(artifact) : null;
236 if (localPath != null) {
237
238 Path path = Paths.get(localPath);
239 if (!Files.isRegularFile(path)) {
240 failures = true;
241 result.addException(
242 ArtifactResult.NO_REPOSITORY, new ArtifactNotFoundException(artifact, localPath));
243 } else {
244 artifact = artifact.setPath(path);
245 result.setArtifact(artifact);
246 artifactResolved(session, trace, artifact, null, result.getExceptions());
247 }
248 continue;
249 }
250
251 List<RemoteRepository> remoteRepositories = request.getRepositories();
252 List<RemoteRepository> filteredRemoteRepositories = new ArrayList<>(remoteRepositories);
253 if (filter != null) {
254 for (RemoteRepository repository : remoteRepositories) {
255 RemoteRepositoryFilter.Result filterResult = filter.acceptArtifact(repository, artifact);
256 if (!filterResult.isAccepted()) {
257 result.addException(
258 repository,
259 new ArtifactFilteredOutException(
260 artifact, repository, filterResult.reasoning()));
261 filteredRemoteRepositories.remove(repository);
262 }
263 }
264 }
265
266 VersionResult versionResult;
267 try {
268 VersionRequest versionRequest =
269 new VersionRequest(artifact, filteredRemoteRepositories, request.getRequestContext());
270 versionRequest.setTrace(trace);
271 versionResult = versionResolver.resolveVersion(session, versionRequest);
272 } catch (VersionResolutionException e) {
273 if (filteredRemoteRepositories.isEmpty()) {
274 result.addException(lrm.getRepository(), e);
275 } else {
276 filteredRemoteRepositories.forEach(r -> result.addException(r, e));
277 }
278 continue;
279 }
280
281 artifact = artifact.setVersion(versionResult.getVersion());
282
283 if (versionResult.getRepository() != null) {
284 if (versionResult.getRepository() instanceof RemoteRepository) {
285 filteredRemoteRepositories =
286 Collections.singletonList((RemoteRepository) versionResult.getRepository());
287 } else {
288 filteredRemoteRepositories = Collections.emptyList();
289 }
290 }
291
292 if (workspace != null) {
293 Path path = workspace.findArtifactPath(artifact);
294 if (path != null) {
295 artifact = artifact.setPath(path);
296 result.setArtifact(artifact);
297 result.setRepository(workspace.getRepository());
298 artifactResolved(session, trace, artifact, result.getRepository(), null);
299 continue;
300 }
301 }
302
303 LocalArtifactResult local = lrm.find(
304 session,
305 new LocalArtifactRequest(
306 artifact, filteredRemoteRepositories, request.getRequestContext()));
307 result.setLocalArtifactResult(local);
308 boolean found = (filter != null && local.isAvailable()) || isLocallyInstalled(local, versionResult);
309
310
311
312 if (found) {
313 if (local.getRepository() != null) {
314 result.setRepository(local.getRepository());
315 } else {
316 result.setRepository(lrm.getRepository());
317 }
318
319 try {
320 artifact = artifact.setPath(getPath(session, artifact, local.getPath()));
321 result.setArtifact(artifact);
322 artifactResolved(session, trace, artifact, result.getRepository(), null);
323 } catch (ArtifactTransferException e) {
324 result.addException(lrm.getRepository(), e);
325 }
326 if (filter == null && simpleLrmInterop && !local.isAvailable()) {
327
328
329
330
331
332
333 lrm.add(session, new LocalArtifactRegistration(artifact));
334 }
335
336 continue;
337 }
338
339 if (local.getPath() != null) {
340 LOGGER.info(
341 "Artifact {} is present in the local repository, but cached from a remote repository ID that is unavailable in current build context, verifying that is downloadable from {}",
342 artifact,
343 remoteRepositories);
344 }
345
346 LOGGER.debug("Resolving artifact {} from {}", artifact, remoteRepositories);
347 AtomicBoolean resolved = new AtomicBoolean(false);
348 Iterator<ResolutionGroup> groupIt = groups.iterator();
349 for (RemoteRepository repo : filteredRemoteRepositories) {
350 if (!repo.getPolicy(artifact.isSnapshot()).isEnabled()) {
351 continue;
352 }
353
354 try {
355 Utils.checkOffline(session, offlineController, repo);
356 } catch (RepositoryOfflineException e) {
357 Exception exception = new ArtifactNotFoundException(
358 artifact,
359 repo,
360 "Cannot access " + repo.getId() + " ("
361 + repo.getUrl() + ") in offline mode and the artifact " + artifact
362 + " has not been downloaded from it before.",
363 e);
364 result.addException(repo, exception);
365 continue;
366 }
367
368 ResolutionGroup group = null;
369 while (groupIt.hasNext()) {
370 ResolutionGroup t = groupIt.next();
371 if (t.matches(repo)) {
372 group = t;
373 break;
374 }
375 }
376 if (group == null) {
377 group = new ResolutionGroup(repo);
378 groups.add(group);
379 groupIt = Collections.emptyIterator();
380 }
381 group.items.add(new ResolutionItem(trace, artifact, resolved, result, local, repo));
382 }
383 }
384
385 if (!groups.isEmpty() && current == shared) {
386 current.close();
387 current = exclusive;
388 continue;
389 }
390
391 for (ResolutionGroup group : groups) {
392 performDownloads(session, group);
393 }
394
395 for (ArtifactResolverPostProcessor artifactResolverPostProcessor :
396 artifactResolverPostProcessors.values()) {
397 artifactResolverPostProcessor.postProcess(session, results);
398 }
399
400 for (ArtifactResult result : results) {
401 ArtifactRequest request = result.getRequest();
402
403 Artifact artifact = result.getArtifact();
404 if (artifact == null || artifact.getPath() == null) {
405 failures = true;
406 if (result.getExceptions().isEmpty()) {
407 Exception exception =
408 new ArtifactNotFoundException(request.getArtifact(), (RemoteRepository) null);
409 result.addException(result.getRepository(), exception);
410 }
411 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
412 artifactResolved(session, trace, request.getArtifact(), null, result.getExceptions());
413 }
414 }
415
416 if (failures) {
417 throw new ArtifactResolutionException(results);
418 }
419
420 return results;
421 }
422 } finally {
423 current.close();
424 }
425 }
426
427 private boolean isLocallyInstalled(LocalArtifactResult lar, VersionResult vr) {
428 if (lar.isAvailable()) {
429 return true;
430 }
431 if (lar.getPath() != null) {
432
433 if (vr.getRepository() instanceof LocalRepository) {
434
435 return true;
436 } else {
437 return vr.getRepository() == null
438 && lar.getRequest().getRepositories().isEmpty();
439 }
440 }
441 return false;
442 }
443
444 private Path getPath(RepositorySystemSession session, Artifact artifact, Path path)
445 throws ArtifactTransferException {
446 if (artifact.isSnapshot()
447 && !artifact.getVersion().equals(artifact.getBaseVersion())
448 && ConfigUtils.getBoolean(
449 session, DEFAULT_SNAPSHOT_NORMALIZATION, CONFIG_PROP_SNAPSHOT_NORMALIZATION)) {
450 String name = path.getFileName().toString().replace(artifact.getVersion(), artifact.getBaseVersion());
451 Path dst = path.getParent().resolve(name);
452
453 try {
454 long pathLastModified = pathProcessor.lastModified(path, 0L);
455 boolean copy = pathProcessor.size(dst, 0L) != pathProcessor.size(path, 0L)
456 || pathProcessor.lastModified(dst, 0L) != pathLastModified;
457 if (copy) {
458 pathProcessor.copy(path, dst);
459 Files.setLastModifiedTime(dst, FileTime.fromMillis(pathLastModified));
460 }
461 } catch (IOException e) {
462 throw new ArtifactTransferException(artifact, null, e);
463 }
464
465 path = dst;
466 }
467
468 return path;
469 }
470
471 private void performDownloads(RepositorySystemSession session, ResolutionGroup group) {
472 List<ArtifactDownload> downloads = gatherDownloads(session, group);
473 if (downloads.isEmpty()) {
474 return;
475 }
476
477 for (ArtifactDownload download : downloads) {
478 artifactDownloading(session, download.getTrace(), download.getArtifact(), group.repository);
479 }
480
481 try {
482 try (RepositoryConnector connector =
483 repositoryConnectorProvider.newRepositoryConnector(session, group.repository)) {
484 connector.get(downloads, null);
485 }
486 } catch (NoRepositoryConnectorException e) {
487 for (ArtifactDownload download : downloads) {
488 download.setException(new ArtifactTransferException(download.getArtifact(), group.repository, e));
489 }
490 }
491
492 evaluateDownloads(session, group);
493 }
494
495 private List<ArtifactDownload> gatherDownloads(RepositorySystemSession session, ResolutionGroup group) {
496 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
497 List<ArtifactDownload> downloads = new ArrayList<>();
498
499 for (ResolutionItem item : group.items) {
500 Artifact artifact = item.artifact;
501
502 if (item.resolved.get()) {
503
504 continue;
505 }
506
507 ArtifactDownload download = new ArtifactDownload();
508 download.setArtifact(artifact);
509 download.setRequestContext(item.request.getRequestContext());
510 download.setListener(SafeTransferListener.wrap(session));
511 download.setTrace(item.trace);
512 if (item.local.getPath() != null) {
513 download.setPath(item.local.getPath());
514 download.setExistenceCheck(true);
515 } else {
516 String path =
517 lrm.getPathForRemoteArtifact(artifact, group.repository, item.request.getRequestContext());
518 download.setPath(lrm.getRepository().getBasePath().resolve(path));
519 }
520
521 boolean snapshot = artifact.isSnapshot();
522 RepositoryPolicy policy = remoteRepositoryManager.getPolicy(session, group.repository, !snapshot, snapshot);
523
524 int errorPolicy = Utils.getPolicy(session, artifact, group.repository);
525 if ((errorPolicy & ResolutionErrorPolicy.CACHE_ALL) != 0) {
526 UpdateCheck<Artifact, ArtifactTransferException> check = new UpdateCheck<>();
527 check.setItem(artifact);
528 check.setPath(download.getPath());
529 check.setFileValid(false);
530 check.setRepository(group.repository);
531 check.setArtifactPolicy(policy.getArtifactUpdatePolicy());
532 check.setMetadataPolicy(policy.getMetadataUpdatePolicy());
533 item.updateCheck = check;
534 updateCheckManager.checkArtifact(session, check);
535 if (!check.isRequired()) {
536 item.result.addException(group.repository, check.getException());
537 continue;
538 }
539 }
540
541 download.setChecksumPolicy(policy.getChecksumPolicy());
542 download.setRepositories(item.repository.getMirroredRepositories());
543 downloads.add(download);
544 item.download = download;
545 }
546
547 return downloads;
548 }
549
550 private void evaluateDownloads(RepositorySystemSession session, ResolutionGroup group) {
551 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
552
553 for (ResolutionItem item : group.items) {
554 ArtifactDownload download = item.download;
555 if (download == null) {
556 continue;
557 }
558
559 Artifact artifact = download.getArtifact();
560 if (download.getException() == null) {
561 item.resolved.set(true);
562 item.result.setRepository(group.repository);
563 try {
564 artifact = artifact.setPath(getPath(session, artifact, download.getPath()));
565 item.result.setArtifact(artifact);
566
567 lrm.add(
568 session,
569 new LocalArtifactRegistration(artifact, group.repository, download.getSupportedContexts()));
570 } catch (ArtifactTransferException e) {
571 download.setException(e);
572 item.result.addException(group.repository, e);
573 }
574 } else {
575 item.result.addException(group.repository, download.getException());
576 }
577
578
579
580
581
582 if (item.updateCheck != null) {
583 item.updateCheck.setException(download.getException());
584 updateCheckManager.touchArtifact(session, item.updateCheck);
585 }
586
587 artifactDownloaded(session, download.getTrace(), artifact, group.repository, download.getException());
588 if (download.getException() == null) {
589 artifactResolved(session, download.getTrace(), artifact, group.repository, null);
590 }
591 }
592 }
593
594 private void artifactResolving(RepositorySystemSession session, RequestTrace trace, Artifact artifact) {
595 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_RESOLVING);
596 event.setTrace(trace);
597 event.setArtifact(artifact);
598
599 repositoryEventDispatcher.dispatch(event.build());
600 }
601
602 private void artifactResolved(
603 RepositorySystemSession session,
604 RequestTrace trace,
605 Artifact artifact,
606 ArtifactRepository repository,
607 Collection<Exception> exceptions) {
608 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_RESOLVED);
609 event.setTrace(trace);
610 event.setArtifact(artifact);
611 event.setRepository(repository);
612 event.setExceptions(exceptions != null ? new ArrayList<>(exceptions) : null);
613 if (artifact != null) {
614 event.setPath(artifact.getPath());
615 }
616
617 repositoryEventDispatcher.dispatch(event.build());
618 }
619
620 private void artifactDownloading(
621 RepositorySystemSession session, RequestTrace trace, Artifact artifact, RemoteRepository repository) {
622 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DOWNLOADING);
623 event.setTrace(trace);
624 event.setArtifact(artifact);
625 event.setRepository(repository);
626
627 repositoryEventDispatcher.dispatch(event.build());
628 }
629
630 private void artifactDownloaded(
631 RepositorySystemSession session,
632 RequestTrace trace,
633 Artifact artifact,
634 RemoteRepository repository,
635 Exception exception) {
636 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DOWNLOADED);
637 event.setTrace(trace);
638 event.setArtifact(artifact);
639 event.setRepository(repository);
640 event.setException(exception);
641 if (artifact != null) {
642 event.setPath(artifact.getPath());
643 }
644
645 repositoryEventDispatcher.dispatch(event.build());
646 }
647
648 static class ResolutionGroup {
649
650 final RemoteRepository repository;
651
652 final List<ResolutionItem> items = new ArrayList<>();
653
654 ResolutionGroup(RemoteRepository repository) {
655 this.repository = repository;
656 }
657
658 boolean matches(RemoteRepository repo) {
659 return repository.getUrl().equals(repo.getUrl())
660 && repository.getContentType().equals(repo.getContentType())
661 && repository.isRepositoryManager() == repo.isRepositoryManager();
662 }
663 }
664
665 static class ResolutionItem {
666
667 final RequestTrace trace;
668
669 final ArtifactRequest request;
670
671 final ArtifactResult result;
672
673 final LocalArtifactResult local;
674
675 final RemoteRepository repository;
676
677 final Artifact artifact;
678
679 final AtomicBoolean resolved;
680
681 ArtifactDownload download;
682
683 UpdateCheck<Artifact, ArtifactTransferException> updateCheck;
684
685 ResolutionItem(
686 RequestTrace trace,
687 Artifact artifact,
688 AtomicBoolean resolved,
689 ArtifactResult result,
690 LocalArtifactResult local,
691 RemoteRepository repository) {
692 this.trace = trace;
693 this.artifact = artifact;
694 this.resolved = resolved;
695 this.result = result;
696 this.request = result.getRequest();
697 this.local = local;
698 this.repository = repository;
699 }
700 }
701 }