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