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.File; 026import java.io.IOException; 027import java.util.ArrayList; 028import java.util.Collection; 029import java.util.Collections; 030import java.util.Iterator; 031import java.util.List; 032import java.util.Map; 033import java.util.concurrent.atomic.AtomicBoolean; 034 035import org.eclipse.aether.RepositoryEvent; 036import org.eclipse.aether.RepositoryEvent.EventType; 037import org.eclipse.aether.RepositorySystemSession; 038import org.eclipse.aether.RequestTrace; 039import org.eclipse.aether.SyncContext; 040import org.eclipse.aether.artifact.Artifact; 041import org.eclipse.aether.artifact.ArtifactProperties; 042import org.eclipse.aether.impl.ArtifactResolver; 043import org.eclipse.aether.impl.OfflineController; 044import org.eclipse.aether.impl.RemoteRepositoryFilterManager; 045import org.eclipse.aether.impl.RemoteRepositoryManager; 046import org.eclipse.aether.impl.RepositoryConnectorProvider; 047import org.eclipse.aether.impl.RepositoryEventDispatcher; 048import org.eclipse.aether.impl.UpdateCheck; 049import org.eclipse.aether.impl.UpdateCheckManager; 050import org.eclipse.aether.impl.VersionResolver; 051import org.eclipse.aether.repository.ArtifactRepository; 052import org.eclipse.aether.repository.LocalArtifactRegistration; 053import org.eclipse.aether.repository.LocalArtifactRequest; 054import org.eclipse.aether.repository.LocalArtifactResult; 055import org.eclipse.aether.repository.LocalRepository; 056import org.eclipse.aether.repository.LocalRepositoryManager; 057import org.eclipse.aether.repository.RemoteRepository; 058import org.eclipse.aether.repository.RepositoryPolicy; 059import org.eclipse.aether.repository.WorkspaceReader; 060import org.eclipse.aether.resolution.ArtifactRequest; 061import org.eclipse.aether.resolution.ArtifactResolutionException; 062import org.eclipse.aether.resolution.ArtifactResult; 063import org.eclipse.aether.resolution.ResolutionErrorPolicy; 064import org.eclipse.aether.resolution.VersionRequest; 065import org.eclipse.aether.resolution.VersionResolutionException; 066import org.eclipse.aether.resolution.VersionResult; 067import org.eclipse.aether.spi.connector.ArtifactDownload; 068import org.eclipse.aether.spi.connector.RepositoryConnector; 069import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter; 070import org.eclipse.aether.spi.io.FileProcessor; 071import org.eclipse.aether.spi.locator.Service; 072import org.eclipse.aether.spi.locator.ServiceLocator; 073import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor; 074import org.eclipse.aether.spi.synccontext.SyncContextFactory; 075import org.eclipse.aether.transfer.ArtifactNotFoundException; 076import org.eclipse.aether.transfer.ArtifactTransferException; 077import org.eclipse.aether.transfer.NoRepositoryConnectorException; 078import org.eclipse.aether.transfer.RepositoryOfflineException; 079import org.eclipse.aether.util.ConfigUtils; 080import org.slf4j.Logger; 081import org.slf4j.LoggerFactory; 082 083import static java.util.Objects.requireNonNull; 084 085/** 086 * 087 */ 088@Singleton 089@Named 090public class DefaultArtifactResolver implements ArtifactResolver, Service { 091 092 /** 093 * Configuration to enable "snapshot normalization", downloaded snapshots from remote with timestamped file names 094 * will have file names converted back to baseVersion. Default: {@code true}. 095 */ 096 private static final String CONFIG_PROP_SNAPSHOT_NORMALIZATION = "aether.artifactResolver.snapshotNormalization"; 097 098 /** 099 * Configuration to enable "interoperability" with Simple LRM, but this breaks RRF feature, hence this configuration 100 * is IGNORED when RRF is used, and is warmly recommended to leave it disabled even if no RRF is being used. 101 * Default: {@code false}. 102 */ 103 private static final String CONFIG_PROP_SIMPLE_LRM_INTEROP = "aether.artifactResolver.simpleLrmInterop"; 104 105 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultArtifactResolver.class); 106 107 private FileProcessor fileProcessor; 108 109 private RepositoryEventDispatcher repositoryEventDispatcher; 110 111 private VersionResolver versionResolver; 112 113 private UpdateCheckManager updateCheckManager; 114 115 private RepositoryConnectorProvider repositoryConnectorProvider; 116 117 private RemoteRepositoryManager remoteRepositoryManager; 118 119 private SyncContextFactory syncContextFactory; 120 121 private OfflineController offlineController; 122 123 private Map<String, ArtifactResolverPostProcessor> artifactResolverPostProcessors; 124 125 private RemoteRepositoryFilterManager remoteRepositoryFilterManager; 126 127 public DefaultArtifactResolver() { 128 // enables default constructor 129 } 130 131 @SuppressWarnings("checkstyle:parameternumber") 132 @Inject 133 DefaultArtifactResolver( 134 FileProcessor fileProcessor, 135 RepositoryEventDispatcher repositoryEventDispatcher, 136 VersionResolver versionResolver, 137 UpdateCheckManager updateCheckManager, 138 RepositoryConnectorProvider repositoryConnectorProvider, 139 RemoteRepositoryManager remoteRepositoryManager, 140 SyncContextFactory syncContextFactory, 141 OfflineController offlineController, 142 Map<String, ArtifactResolverPostProcessor> artifactResolverPostProcessors, 143 RemoteRepositoryFilterManager remoteRepositoryFilterManager) { 144 setFileProcessor(fileProcessor); 145 setRepositoryEventDispatcher(repositoryEventDispatcher); 146 setVersionResolver(versionResolver); 147 setUpdateCheckManager(updateCheckManager); 148 setRepositoryConnectorProvider(repositoryConnectorProvider); 149 setRemoteRepositoryManager(remoteRepositoryManager); 150 setSyncContextFactory(syncContextFactory); 151 setOfflineController(offlineController); 152 setArtifactResolverPostProcessors(artifactResolverPostProcessors); 153 setRemoteRepositoryFilterManager(remoteRepositoryFilterManager); 154 } 155 156 public void initService(ServiceLocator locator) { 157 setFileProcessor(locator.getService(FileProcessor.class)); 158 setRepositoryEventDispatcher(locator.getService(RepositoryEventDispatcher.class)); 159 setVersionResolver(locator.getService(VersionResolver.class)); 160 setUpdateCheckManager(locator.getService(UpdateCheckManager.class)); 161 setRepositoryConnectorProvider(locator.getService(RepositoryConnectorProvider.class)); 162 setRemoteRepositoryManager(locator.getService(RemoteRepositoryManager.class)); 163 setSyncContextFactory(locator.getService(SyncContextFactory.class)); 164 setOfflineController(locator.getService(OfflineController.class)); 165 setArtifactResolverPostProcessors(Collections.emptyMap()); 166 setRemoteRepositoryFilterManager(locator.getService(RemoteRepositoryFilterManager.class)); 167 } 168 169 /** 170 * @deprecated not used any more since MRESOLVER-36 move to slf4j, added back in MRESOLVER-64 for compatibility 171 */ 172 @Deprecated 173 public DefaultArtifactResolver setLoggerFactory(org.eclipse.aether.spi.log.LoggerFactory loggerFactory) { 174 // this.logger = NullLoggerFactory.getSafeLogger( loggerFactory, getClass() ); 175 return this; 176 } 177 178 public DefaultArtifactResolver setFileProcessor(FileProcessor fileProcessor) { 179 this.fileProcessor = requireNonNull(fileProcessor, "file processor cannot be null"); 180 return this; 181 } 182 183 public DefaultArtifactResolver setRepositoryEventDispatcher(RepositoryEventDispatcher repositoryEventDispatcher) { 184 this.repositoryEventDispatcher = 185 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null"); 186 return this; 187 } 188 189 public DefaultArtifactResolver setVersionResolver(VersionResolver versionResolver) { 190 this.versionResolver = requireNonNull(versionResolver, "version resolver cannot be null"); 191 return this; 192 } 193 194 public DefaultArtifactResolver setUpdateCheckManager(UpdateCheckManager updateCheckManager) { 195 this.updateCheckManager = requireNonNull(updateCheckManager, "update check manager cannot be null"); 196 return this; 197 } 198 199 public DefaultArtifactResolver setRepositoryConnectorProvider( 200 RepositoryConnectorProvider repositoryConnectorProvider) { 201 this.repositoryConnectorProvider = 202 requireNonNull(repositoryConnectorProvider, "repository connector provider cannot be null"); 203 return this; 204 } 205 206 public DefaultArtifactResolver setRemoteRepositoryManager(RemoteRepositoryManager remoteRepositoryManager) { 207 this.remoteRepositoryManager = 208 requireNonNull(remoteRepositoryManager, "remote repository provider cannot be null"); 209 return this; 210 } 211 212 public DefaultArtifactResolver setSyncContextFactory(SyncContextFactory syncContextFactory) { 213 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null"); 214 return this; 215 } 216 217 public DefaultArtifactResolver setOfflineController(OfflineController offlineController) { 218 this.offlineController = requireNonNull(offlineController, "offline controller cannot be null"); 219 return this; 220 } 221 222 public DefaultArtifactResolver setArtifactResolverPostProcessors( 223 Map<String, ArtifactResolverPostProcessor> artifactResolverPostProcessors) { 224 this.artifactResolverPostProcessors = 225 requireNonNull(artifactResolverPostProcessors, "artifact resolver post-processors cannot be null"); 226 return this; 227 } 228 229 public DefaultArtifactResolver setRemoteRepositoryFilterManager( 230 RemoteRepositoryFilterManager remoteRepositoryFilterManager) { 231 this.remoteRepositoryFilterManager = 232 requireNonNull(remoteRepositoryFilterManager, "remote repository filter manager cannot be null"); 233 return this; 234 } 235 236 public ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request) 237 throws ArtifactResolutionException { 238 requireNonNull(session, "session cannot be null"); 239 requireNonNull(session, "session cannot be null"); 240 241 return resolveArtifacts(session, Collections.singleton(request)).get(0); 242 } 243 244 public List<ArtifactResult> resolveArtifacts( 245 RepositorySystemSession session, Collection<? extends ArtifactRequest> requests) 246 throws ArtifactResolutionException { 247 requireNonNull(session, "session cannot be null"); 248 requireNonNull(session, "session cannot be null"); 249 try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) { 250 Collection<Artifact> artifacts = new ArrayList<>(requests.size()); 251 for (ArtifactRequest request : requests) { 252 if (request.getArtifact().getProperty(ArtifactProperties.LOCAL_PATH, null) != null) { 253 continue; 254 } 255 artifacts.add(request.getArtifact()); 256 } 257 258 syncContext.acquire(artifacts, null); 259 260 return resolve(session, requests); 261 } 262 } 263 264 @SuppressWarnings("checkstyle:methodlength") 265 private List<ArtifactResult> resolve( 266 RepositorySystemSession session, Collection<? extends ArtifactRequest> requests) 267 throws ArtifactResolutionException { 268 List<ArtifactResult> results = new ArrayList<>(requests.size()); 269 boolean failures = false; 270 final boolean simpleLrmInterop = ConfigUtils.getBoolean(session, false, CONFIG_PROP_SIMPLE_LRM_INTEROP); 271 272 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 273 WorkspaceReader workspace = session.getWorkspaceReader(); 274 275 List<ResolutionGroup> groups = new ArrayList<>(); 276 // filter != null: means "filtering applied", if null no filtering applied (behave as before) 277 RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session); 278 279 for (ArtifactRequest request : requests) { 280 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 281 282 ArtifactResult result = new ArtifactResult(request); 283 results.add(result); 284 285 Artifact artifact = request.getArtifact(); 286 287 artifactResolving(session, trace, artifact); 288 289 String localPath = artifact.getProperty(ArtifactProperties.LOCAL_PATH, null); 290 if (localPath != null) { 291 // unhosted artifact, just validate file 292 File file = new File(localPath); 293 if (!file.isFile()) { 294 failures = true; 295 result.addException(new ArtifactNotFoundException(artifact, null)); 296 } else { 297 artifact = artifact.setFile(file); 298 result.setArtifact(artifact); 299 artifactResolved(session, trace, artifact, null, result.getExceptions()); 300 } 301 continue; 302 } 303 304 List<RemoteRepository> remoteRepositories = request.getRepositories(); 305 List<RemoteRepository> filteredRemoteRepositories = new ArrayList<>(remoteRepositories); 306 if (filter != null) { 307 for (RemoteRepository repository : remoteRepositories) { 308 RemoteRepositoryFilter.Result filterResult = filter.acceptArtifact(repository, artifact); 309 if (!filterResult.isAccepted()) { 310 result.addException( 311 new ArtifactNotFoundException(artifact, repository, filterResult.reasoning())); 312 filteredRemoteRepositories.remove(repository); 313 } 314 } 315 } 316 317 VersionResult versionResult; 318 try { 319 VersionRequest versionRequest = 320 new VersionRequest(artifact, filteredRemoteRepositories, request.getRequestContext()); 321 versionRequest.setTrace(trace); 322 versionResult = versionResolver.resolveVersion(session, versionRequest); 323 } catch (VersionResolutionException e) { 324 result.addException(e); 325 continue; 326 } 327 328 artifact = artifact.setVersion(versionResult.getVersion()); 329 330 if (versionResult.getRepository() != null) { 331 if (versionResult.getRepository() instanceof RemoteRepository) { 332 filteredRemoteRepositories = 333 Collections.singletonList((RemoteRepository) versionResult.getRepository()); 334 } else { 335 filteredRemoteRepositories = Collections.emptyList(); 336 } 337 } 338 339 if (workspace != null) { 340 File file = workspace.findArtifact(artifact); 341 if (file != null) { 342 artifact = artifact.setFile(file); 343 result.setArtifact(artifact); 344 result.setRepository(workspace.getRepository()); 345 artifactResolved(session, trace, artifact, result.getRepository(), null); 346 continue; 347 } 348 } 349 350 LocalArtifactResult local = lrm.find( 351 session, 352 new LocalArtifactRequest(artifact, filteredRemoteRepositories, request.getRequestContext())); 353 boolean found = (filter != null && local.isAvailable()) || isLocallyInstalled(local, versionResult); 354 // with filtering it is availability that drives logic 355 // without filtering it is simply presence of file that drives the logic 356 // "interop" logic with simple LRM leads to RRF breakage: hence is ignored when filtering in effect 357 if (found) { 358 if (local.getRepository() != null) { 359 result.setRepository(local.getRepository()); 360 } else { 361 result.setRepository(lrm.getRepository()); 362 } 363 364 try { 365 artifact = artifact.setFile(getFile(session, artifact, local.getFile())); 366 result.setArtifact(artifact); 367 artifactResolved(session, trace, artifact, result.getRepository(), null); 368 } catch (ArtifactTransferException e) { 369 result.addException(e); 370 } 371 if (filter == null && simpleLrmInterop && !local.isAvailable()) { 372 /* 373 * NOTE: Interop with simple local repository: An artifact installed by a simple local repo 374 * manager will not show up in the repository tracking file of the enhanced local repository. 375 * If however the maven-metadata-local.xml tells us the artifact was installed locally, we 376 * sync the repository tracking file. 377 */ 378 lrm.add(session, new LocalArtifactRegistration(artifact)); 379 } 380 381 continue; 382 } 383 384 if (local.getFile() != null) { 385 LOGGER.debug("Verifying availability of {} from {}", local.getFile(), remoteRepositories); 386 } 387 388 LOGGER.debug("Resolving artifact {} from {}", artifact, remoteRepositories); 389 AtomicBoolean resolved = new AtomicBoolean(false); 390 Iterator<ResolutionGroup> groupIt = groups.iterator(); 391 for (RemoteRepository repo : filteredRemoteRepositories) { 392 if (!repo.getPolicy(artifact.isSnapshot()).isEnabled()) { 393 continue; 394 } 395 396 try { 397 Utils.checkOffline(session, offlineController, repo); 398 } catch (RepositoryOfflineException e) { 399 Exception exception = new ArtifactNotFoundException( 400 artifact, 401 repo, 402 "Cannot access " + repo.getId() + " (" 403 + repo.getUrl() + ") in offline mode and the artifact " + artifact 404 + " has not been downloaded from it before.", 405 e); 406 result.addException(exception); 407 continue; 408 } 409 410 ResolutionGroup group = null; 411 while (groupIt.hasNext()) { 412 ResolutionGroup t = groupIt.next(); 413 if (t.matches(repo)) { 414 group = t; 415 break; 416 } 417 } 418 if (group == null) { 419 group = new ResolutionGroup(repo); 420 groups.add(group); 421 groupIt = Collections.emptyIterator(); 422 } 423 group.items.add(new ResolutionItem(trace, artifact, resolved, result, local, repo)); 424 } 425 } 426 427 for (ResolutionGroup group : groups) { 428 performDownloads(session, group); 429 } 430 431 for (ArtifactResolverPostProcessor artifactResolverPostProcessor : artifactResolverPostProcessors.values()) { 432 artifactResolverPostProcessor.postProcess(session, results); 433 } 434 435 for (ArtifactResult result : results) { 436 ArtifactRequest request = result.getRequest(); 437 438 Artifact artifact = result.getArtifact(); 439 if (artifact == null || artifact.getFile() == null) { 440 failures = true; 441 if (result.getExceptions().isEmpty()) { 442 Exception exception = new ArtifactNotFoundException(request.getArtifact(), null); 443 result.addException(exception); 444 } 445 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 446 artifactResolved(session, trace, request.getArtifact(), null, result.getExceptions()); 447 } 448 } 449 450 if (failures) { 451 throw new ArtifactResolutionException(results); 452 } 453 454 return results; 455 } 456 457 private boolean isLocallyInstalled(LocalArtifactResult lar, VersionResult vr) { 458 if (lar.isAvailable()) { 459 return true; 460 } 461 if (lar.getFile() != null) { 462 if (vr.getRepository() instanceof LocalRepository) { 463 // resolution of (snapshot) version found locally installed artifact 464 return true; 465 } else if (vr.getRepository() == null 466 && lar.getRequest().getRepositories().isEmpty()) { 467 // resolution of version range found locally installed artifact 468 return true; 469 } 470 } 471 return false; 472 } 473 474 private File getFile(RepositorySystemSession session, Artifact artifact, File file) 475 throws ArtifactTransferException { 476 if (artifact.isSnapshot() 477 && !artifact.getVersion().equals(artifact.getBaseVersion()) 478 && ConfigUtils.getBoolean(session, true, CONFIG_PROP_SNAPSHOT_NORMALIZATION)) { 479 String name = file.getName().replace(artifact.getVersion(), artifact.getBaseVersion()); 480 File dst = new File(file.getParent(), name); 481 482 boolean copy = dst.length() != file.length() || dst.lastModified() != file.lastModified(); 483 if (copy) { 484 try { 485 fileProcessor.copy(file, dst); 486 dst.setLastModified(file.lastModified()); 487 } catch (IOException e) { 488 throw new ArtifactTransferException(artifact, null, e); 489 } 490 } 491 492 file = dst; 493 } 494 495 return file; 496 } 497 498 private void performDownloads(RepositorySystemSession session, ResolutionGroup group) { 499 List<ArtifactDownload> downloads = gatherDownloads(session, group); 500 if (downloads.isEmpty()) { 501 return; 502 } 503 504 for (ArtifactDownload download : downloads) { 505 artifactDownloading(session, download.getTrace(), download.getArtifact(), group.repository); 506 } 507 508 try { 509 try (RepositoryConnector connector = 510 repositoryConnectorProvider.newRepositoryConnector(session, group.repository)) { 511 connector.get(downloads, null); 512 } 513 } catch (NoRepositoryConnectorException e) { 514 for (ArtifactDownload download : downloads) { 515 download.setException(new ArtifactTransferException(download.getArtifact(), group.repository, e)); 516 } 517 } 518 519 evaluateDownloads(session, group); 520 } 521 522 private List<ArtifactDownload> gatherDownloads(RepositorySystemSession session, ResolutionGroup group) { 523 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 524 List<ArtifactDownload> downloads = new ArrayList<>(); 525 526 for (ResolutionItem item : group.items) { 527 Artifact artifact = item.artifact; 528 529 if (item.resolved.get()) { 530 // resolved in previous resolution group 531 continue; 532 } 533 534 ArtifactDownload download = new ArtifactDownload(); 535 download.setArtifact(artifact); 536 download.setRequestContext(item.request.getRequestContext()); 537 download.setListener(SafeTransferListener.wrap(session)); 538 download.setTrace(item.trace); 539 if (item.local.getFile() != null) { 540 download.setFile(item.local.getFile()); 541 download.setExistenceCheck(true); 542 } else { 543 String path = 544 lrm.getPathForRemoteArtifact(artifact, group.repository, item.request.getRequestContext()); 545 download.setFile(new File(lrm.getRepository().getBasedir(), path)); 546 } 547 548 boolean snapshot = artifact.isSnapshot(); 549 RepositoryPolicy policy = remoteRepositoryManager.getPolicy(session, group.repository, !snapshot, snapshot); 550 551 int errorPolicy = Utils.getPolicy(session, artifact, group.repository); 552 if ((errorPolicy & ResolutionErrorPolicy.CACHE_ALL) != 0) { 553 UpdateCheck<Artifact, ArtifactTransferException> check = new UpdateCheck<>(); 554 check.setItem(artifact); 555 check.setFile(download.getFile()); 556 check.setFileValid(false); 557 check.setRepository(group.repository); 558 check.setPolicy(policy.getUpdatePolicy()); 559 item.updateCheck = check; 560 updateCheckManager.checkArtifact(session, check); 561 if (!check.isRequired()) { 562 item.result.addException(check.getException()); 563 continue; 564 } 565 } 566 567 download.setChecksumPolicy(policy.getChecksumPolicy()); 568 download.setRepositories(item.repository.getMirroredRepositories()); 569 downloads.add(download); 570 item.download = download; 571 } 572 573 return downloads; 574 } 575 576 private void evaluateDownloads(RepositorySystemSession session, ResolutionGroup group) { 577 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 578 579 for (ResolutionItem item : group.items) { 580 ArtifactDownload download = item.download; 581 if (download == null) { 582 continue; 583 } 584 585 Artifact artifact = download.getArtifact(); 586 if (download.getException() == null) { 587 item.resolved.set(true); 588 item.result.setRepository(group.repository); 589 try { 590 artifact = artifact.setFile(getFile(session, artifact, download.getFile())); 591 item.result.setArtifact(artifact); 592 593 lrm.add( 594 session, 595 new LocalArtifactRegistration(artifact, group.repository, download.getSupportedContexts())); 596 } catch (ArtifactTransferException e) { 597 download.setException(e); 598 item.result.addException(e); 599 } 600 } else { 601 item.result.addException(download.getException()); 602 } 603 604 /* 605 * NOTE: Touch after registration with local repo to ensure concurrent resolution is not rejected with 606 * "already updated" via session data when actual update to local repo is still pending. 607 */ 608 if (item.updateCheck != null) { 609 item.updateCheck.setException(download.getException()); 610 updateCheckManager.touchArtifact(session, item.updateCheck); 611 } 612 613 artifactDownloaded(session, download.getTrace(), artifact, group.repository, download.getException()); 614 if (download.getException() == null) { 615 artifactResolved(session, download.getTrace(), artifact, group.repository, null); 616 } 617 } 618 } 619 620 private void artifactResolving(RepositorySystemSession session, RequestTrace trace, Artifact artifact) { 621 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_RESOLVING); 622 event.setTrace(trace); 623 event.setArtifact(artifact); 624 625 repositoryEventDispatcher.dispatch(event.build()); 626 } 627 628 private void artifactResolved( 629 RepositorySystemSession session, 630 RequestTrace trace, 631 Artifact artifact, 632 ArtifactRepository repository, 633 List<Exception> exceptions) { 634 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_RESOLVED); 635 event.setTrace(trace); 636 event.setArtifact(artifact); 637 event.setRepository(repository); 638 event.setExceptions(exceptions); 639 if (artifact != null) { 640 event.setFile(artifact.getFile()); 641 } 642 643 repositoryEventDispatcher.dispatch(event.build()); 644 } 645 646 private void artifactDownloading( 647 RepositorySystemSession session, RequestTrace trace, Artifact artifact, RemoteRepository repository) { 648 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DOWNLOADING); 649 event.setTrace(trace); 650 event.setArtifact(artifact); 651 event.setRepository(repository); 652 653 repositoryEventDispatcher.dispatch(event.build()); 654 } 655 656 private void artifactDownloaded( 657 RepositorySystemSession session, 658 RequestTrace trace, 659 Artifact artifact, 660 RemoteRepository repository, 661 Exception exception) { 662 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DOWNLOADED); 663 event.setTrace(trace); 664 event.setArtifact(artifact); 665 event.setRepository(repository); 666 event.setException(exception); 667 if (artifact != null) { 668 event.setFile(artifact.getFile()); 669 } 670 671 repositoryEventDispatcher.dispatch(event.build()); 672 } 673 674 static class ResolutionGroup { 675 676 final RemoteRepository repository; 677 678 final List<ResolutionItem> items = new ArrayList<>(); 679 680 ResolutionGroup(RemoteRepository repository) { 681 this.repository = repository; 682 } 683 684 boolean matches(RemoteRepository repo) { 685 return repository.getUrl().equals(repo.getUrl()) 686 && repository.getContentType().equals(repo.getContentType()) 687 && repository.isRepositoryManager() == repo.isRepositoryManager(); 688 } 689 } 690 691 static class ResolutionItem { 692 693 final RequestTrace trace; 694 695 final ArtifactRequest request; 696 697 final ArtifactResult result; 698 699 final LocalArtifactResult local; 700 701 final RemoteRepository repository; 702 703 final Artifact artifact; 704 705 final AtomicBoolean resolved; 706 707 ArtifactDownload download; 708 709 UpdateCheck<Artifact, ArtifactTransferException> updateCheck; 710 711 ResolutionItem( 712 RequestTrace trace, 713 Artifact artifact, 714 AtomicBoolean resolved, 715 ArtifactResult result, 716 LocalArtifactResult local, 717 RemoteRepository repository) { 718 this.trace = trace; 719 this.artifact = artifact; 720 this.resolved = resolved; 721 this.result = result; 722 this.request = result.getRequest(); 723 this.local = local; 724 this.repository = repository; 725 } 726 } 727}