001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.io.IOException; 026import java.nio.file.Files; 027import java.nio.file.Path; 028import java.nio.file.Paths; 029import java.nio.file.attribute.FileTime; 030import java.util.ArrayList; 031import java.util.Collection; 032import java.util.Collections; 033import java.util.Iterator; 034import java.util.List; 035import java.util.Map; 036import java.util.concurrent.atomic.AtomicBoolean; 037 038import org.eclipse.aether.ConfigurationProperties; 039import org.eclipse.aether.RepositoryEvent; 040import org.eclipse.aether.RepositoryEvent.EventType; 041import org.eclipse.aether.RepositorySystemSession; 042import org.eclipse.aether.RequestTrace; 043import org.eclipse.aether.SyncContext; 044import org.eclipse.aether.artifact.Artifact; 045import org.eclipse.aether.impl.ArtifactResolver; 046import org.eclipse.aether.impl.OfflineController; 047import org.eclipse.aether.impl.RemoteRepositoryFilterManager; 048import org.eclipse.aether.impl.RemoteRepositoryManager; 049import org.eclipse.aether.impl.RepositoryConnectorProvider; 050import org.eclipse.aether.impl.RepositoryEventDispatcher; 051import org.eclipse.aether.impl.UpdateCheck; 052import org.eclipse.aether.impl.UpdateCheckManager; 053import org.eclipse.aether.impl.VersionResolver; 054import org.eclipse.aether.repository.*; 055import org.eclipse.aether.resolution.ArtifactRequest; 056import org.eclipse.aether.resolution.ArtifactResolutionException; 057import org.eclipse.aether.resolution.ArtifactResult; 058import org.eclipse.aether.resolution.ResolutionErrorPolicy; 059import org.eclipse.aether.resolution.VersionRequest; 060import org.eclipse.aether.resolution.VersionResolutionException; 061import org.eclipse.aether.resolution.VersionResult; 062import org.eclipse.aether.scope.SystemDependencyScope; 063import org.eclipse.aether.spi.connector.ArtifactDownload; 064import org.eclipse.aether.spi.connector.RepositoryConnector; 065import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter; 066import org.eclipse.aether.spi.io.PathProcessor; 067import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor; 068import org.eclipse.aether.spi.synccontext.SyncContextFactory; 069import org.eclipse.aether.transfer.ArtifactFilteredOutException; 070import org.eclipse.aether.transfer.ArtifactNotFoundException; 071import org.eclipse.aether.transfer.ArtifactTransferException; 072import org.eclipse.aether.transfer.NoRepositoryConnectorException; 073import org.eclipse.aether.transfer.RepositoryOfflineException; 074import org.eclipse.aether.util.ConfigUtils; 075import org.slf4j.Logger; 076import org.slf4j.LoggerFactory; 077 078import static java.util.Objects.requireNonNull; 079 080/** 081 * 082 */ 083@Singleton 084@Named 085public class DefaultArtifactResolver implements ArtifactResolver { 086 087 public static final String CONFIG_PROPS_PREFIX = ConfigurationProperties.PREFIX_AETHER + "artifactResolver."; 088 089 /** 090 * Configuration to enable "snapshot normalization", downloaded snapshots from remote with timestamped file names 091 * will have file names converted back to baseVersion. It replaces the timestamped snapshot file name with a 092 * filename containing the SNAPSHOT qualifier only. This only affects resolving/retrieving artifacts but not 093 * uploading those. 094 * 095 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 096 * @configurationType {@link java.lang.Boolean} 097 * @configurationDefaultValue {@link #DEFAULT_SNAPSHOT_NORMALIZATION} 098 */ 099 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 * Configuration to enable "interoperability" with Simple LRM, but this breaks RRF feature, hence this configuration 105 * is IGNORED when RRF is used, and is warmly recommended to leave it disabled even if no RRF is being used. 106 * 107 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 108 * @configurationType {@link java.lang.Boolean} 109 * @configurationDefaultValue {@link #DEFAULT_SIMPLE_LRM_INTEROP} 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 // filter != null: means "filtering applied", if null no filtering applied (behave as before) 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 // unhosted artifact, just validate file 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 // with filtering it is availability that drives logic 310 // without filtering it is simply presence of file that drives the logic 311 // "interop" logic with simple LRM leads to RRF breakage: hence is ignored when filtering in effect 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 * NOTE: Interop with simple local repository: An artifact installed by a simple local repo 329 * manager will not show up in the repository tracking file of the enhanced local repository. 330 * If however the maven-metadata-local.xml tells us the artifact was installed locally, we 331 * sync the repository tracking file. 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 // resolution of version range found locally installed artifact 433 if (vr.getRepository() instanceof LocalRepository) { 434 // resolution of (snapshot) version found locally installed artifact 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 // resolved in previous resolution group 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 * NOTE: Touch after registration with local repo to ensure concurrent resolution is not rejected with 580 * "already updated" via session data when actual update to local repo is still pending. 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}