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.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 for (ArtifactRequest request : requests) { 185 if (session.getSystemScopeHandler().getSystemPath(request.getArtifact()) != null) { 186 continue; 187 } 188 artifacts.add(request.getArtifact()); 189 } 190 191 return resolve(shared, exclusive, artifacts, session, requests); 192 } 193 } 194 195 @SuppressWarnings("checkstyle:methodlength") 196 private List<ArtifactResult> resolve( 197 SyncContext shared, 198 SyncContext exclusive, 199 Collection<Artifact> subjects, 200 RepositorySystemSession session, 201 Collection<? extends ArtifactRequest> requests) 202 throws ArtifactResolutionException { 203 SyncContext current = shared; 204 try { 205 while (true) { 206 current.acquire(subjects, null); 207 208 boolean failures = false; 209 final List<ArtifactResult> results = new ArrayList<>(requests.size()); 210 final boolean simpleLrmInterop = 211 ConfigUtils.getBoolean(session, DEFAULT_SIMPLE_LRM_INTEROP, CONFIG_PROP_SIMPLE_LRM_INTEROP); 212 final LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 213 final WorkspaceReader workspace = session.getWorkspaceReader(); 214 final List<ResolutionGroup> groups = new ArrayList<>(); 215 // filter != null: means "filtering applied", if null no filtering applied (behave as before) 216 final RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session); 217 218 for (ArtifactRequest request : requests) { 219 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 220 221 ArtifactResult result = new ArtifactResult(request); 222 results.add(result); 223 224 Artifact artifact = request.getArtifact(); 225 226 if (current == shared) { 227 artifactResolving(session, trace, artifact); 228 } 229 230 String localPath = session.getSystemScopeHandler().getSystemPath(artifact); 231 if (localPath != null) { 232 // unhosted artifact, just validate file 233 Path path = Paths.get(localPath); 234 if (!Files.isRegularFile(path)) { 235 failures = true; 236 result.addException( 237 ArtifactResult.NO_REPOSITORY, new ArtifactNotFoundException(artifact, localPath)); 238 } else { 239 artifact = artifact.setPath(path); 240 result.setArtifact(artifact); 241 artifactResolved(session, trace, artifact, null, result.getExceptions()); 242 } 243 continue; 244 } 245 246 List<RemoteRepository> remoteRepositories = request.getRepositories(); 247 List<RemoteRepository> filteredRemoteRepositories = new ArrayList<>(remoteRepositories); 248 if (filter != null) { 249 for (RemoteRepository repository : remoteRepositories) { 250 RemoteRepositoryFilter.Result filterResult = filter.acceptArtifact(repository, artifact); 251 if (!filterResult.isAccepted()) { 252 result.addException( 253 repository, 254 new ArtifactFilteredOutException( 255 artifact, repository, filterResult.reasoning())); 256 filteredRemoteRepositories.remove(repository); 257 } 258 } 259 } 260 261 VersionResult versionResult; 262 try { 263 VersionRequest versionRequest = 264 new VersionRequest(artifact, filteredRemoteRepositories, request.getRequestContext()); 265 versionRequest.setTrace(trace); 266 versionResult = versionResolver.resolveVersion(session, versionRequest); 267 } catch (VersionResolutionException e) { 268 if (filteredRemoteRepositories.isEmpty()) { 269 result.addException(lrm.getRepository(), e); 270 } else { 271 filteredRemoteRepositories.forEach(r -> result.addException(r, e)); 272 } 273 continue; 274 } 275 276 artifact = artifact.setVersion(versionResult.getVersion()); 277 278 if (versionResult.getRepository() != null) { 279 if (versionResult.getRepository() instanceof RemoteRepository) { 280 filteredRemoteRepositories = 281 Collections.singletonList((RemoteRepository) versionResult.getRepository()); 282 } else { 283 filteredRemoteRepositories = Collections.emptyList(); 284 } 285 } 286 287 if (workspace != null) { 288 Path path = workspace.findArtifactPath(artifact); 289 if (path != null) { 290 artifact = artifact.setPath(path); 291 result.setArtifact(artifact); 292 result.setRepository(workspace.getRepository()); 293 artifactResolved(session, trace, artifact, result.getRepository(), null); 294 continue; 295 } 296 } 297 298 LocalArtifactResult local = lrm.find( 299 session, 300 new LocalArtifactRequest( 301 artifact, filteredRemoteRepositories, request.getRequestContext())); 302 result.setLocalArtifactResult(local); 303 boolean found = (filter != null && local.isAvailable()) || isLocallyInstalled(local, versionResult); 304 // with filtering it is availability that drives logic 305 // without filtering it is simply presence of file that drives the logic 306 // "interop" logic with simple LRM leads to RRF breakage: hence is ignored when filtering in effect 307 if (found) { 308 if (local.getRepository() != null) { 309 result.setRepository(local.getRepository()); 310 } else { 311 result.setRepository(lrm.getRepository()); 312 } 313 314 try { 315 artifact = artifact.setPath(getPath(session, artifact, local.getPath())); 316 result.setArtifact(artifact); 317 artifactResolved(session, trace, artifact, result.getRepository(), null); 318 } catch (ArtifactTransferException e) { 319 result.addException(lrm.getRepository(), e); 320 } 321 if (filter == null && simpleLrmInterop && !local.isAvailable()) { 322 /* 323 * NOTE: Interop with simple local repository: An artifact installed by a simple local repo 324 * manager will not show up in the repository tracking file of the enhanced local repository. 325 * If however the maven-metadata-local.xml tells us the artifact was installed locally, we 326 * sync the repository tracking file. 327 */ 328 lrm.add(session, new LocalArtifactRegistration(artifact)); 329 } 330 331 continue; 332 } 333 334 if (local.getPath() != null) { 335 LOGGER.info( 336 "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 {}", 337 artifact, 338 remoteRepositories); 339 } 340 341 LOGGER.debug("Resolving artifact {} from {}", artifact, remoteRepositories); 342 AtomicBoolean resolved = new AtomicBoolean(false); 343 Iterator<ResolutionGroup> groupIt = groups.iterator(); 344 for (RemoteRepository repo : filteredRemoteRepositories) { 345 if (!repo.getPolicy(artifact.isSnapshot()).isEnabled()) { 346 continue; 347 } 348 349 try { 350 Utils.checkOffline(session, offlineController, repo); 351 } catch (RepositoryOfflineException e) { 352 Exception exception = new ArtifactNotFoundException( 353 artifact, 354 repo, 355 "Cannot access " + repo.getId() + " (" 356 + repo.getUrl() + ") in offline mode and the artifact " + artifact 357 + " has not been downloaded from it before.", 358 e); 359 result.addException(repo, exception); 360 continue; 361 } 362 363 ResolutionGroup group = null; 364 while (groupIt.hasNext()) { 365 ResolutionGroup t = groupIt.next(); 366 if (t.matches(repo)) { 367 group = t; 368 break; 369 } 370 } 371 if (group == null) { 372 group = new ResolutionGroup(repo); 373 groups.add(group); 374 groupIt = Collections.emptyIterator(); 375 } 376 group.items.add(new ResolutionItem(trace, artifact, resolved, result, local, repo)); 377 } 378 } 379 380 if (!groups.isEmpty() && current == shared) { 381 current.close(); 382 current = exclusive; 383 continue; 384 } 385 386 for (ResolutionGroup group : groups) { 387 performDownloads(session, group); 388 } 389 390 for (ArtifactResolverPostProcessor artifactResolverPostProcessor : 391 artifactResolverPostProcessors.values()) { 392 artifactResolverPostProcessor.postProcess(session, results); 393 } 394 395 for (ArtifactResult result : results) { 396 ArtifactRequest request = result.getRequest(); 397 398 Artifact artifact = result.getArtifact(); 399 if (artifact == null || artifact.getPath() == null) { 400 failures = true; 401 if (result.getExceptions().isEmpty()) { 402 Exception exception = 403 new ArtifactNotFoundException(request.getArtifact(), (RemoteRepository) null); 404 result.addException(result.getRepository(), exception); 405 } 406 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 407 artifactResolved(session, trace, request.getArtifact(), null, result.getExceptions()); 408 } 409 } 410 411 if (failures) { 412 throw new ArtifactResolutionException(results); 413 } 414 415 return results; 416 } 417 } finally { 418 current.close(); 419 } 420 } 421 422 private boolean isLocallyInstalled(LocalArtifactResult lar, VersionResult vr) { 423 if (lar.isAvailable()) { 424 return true; 425 } 426 if (lar.getPath() != null) { 427 // resolution of version range found locally installed artifact 428 if (vr.getRepository() instanceof LocalRepository) { 429 // resolution of (snapshot) version found locally installed artifact 430 return true; 431 } else { 432 return vr.getRepository() == null 433 && lar.getRequest().getRepositories().isEmpty(); 434 } 435 } 436 return false; 437 } 438 439 private Path getPath(RepositorySystemSession session, Artifact artifact, Path path) 440 throws ArtifactTransferException { 441 if (artifact.isSnapshot() 442 && !artifact.getVersion().equals(artifact.getBaseVersion()) 443 && ConfigUtils.getBoolean( 444 session, DEFAULT_SNAPSHOT_NORMALIZATION, CONFIG_PROP_SNAPSHOT_NORMALIZATION)) { 445 String name = path.getFileName().toString().replace(artifact.getVersion(), artifact.getBaseVersion()); 446 Path dst = path.getParent().resolve(name); 447 448 try { 449 long pathLastModified = pathProcessor.lastModified(path, 0L); 450 boolean copy = pathProcessor.size(dst, 0L) != pathProcessor.size(path, 0L) 451 || pathProcessor.lastModified(dst, 0L) != pathLastModified; 452 if (copy) { 453 pathProcessor.copy(path, dst); 454 Files.setLastModifiedTime(dst, FileTime.fromMillis(pathLastModified)); 455 } 456 } catch (IOException e) { 457 throw new ArtifactTransferException(artifact, null, e); 458 } 459 460 path = dst; 461 } 462 463 return path; 464 } 465 466 private void performDownloads(RepositorySystemSession session, ResolutionGroup group) { 467 List<ArtifactDownload> downloads = gatherDownloads(session, group); 468 if (downloads.isEmpty()) { 469 return; 470 } 471 472 for (ArtifactDownload download : downloads) { 473 artifactDownloading(session, download.getTrace(), download.getArtifact(), group.repository); 474 } 475 476 try { 477 try (RepositoryConnector connector = 478 repositoryConnectorProvider.newRepositoryConnector(session, group.repository)) { 479 connector.get(downloads, null); 480 } 481 } catch (NoRepositoryConnectorException e) { 482 for (ArtifactDownload download : downloads) { 483 download.setException(new ArtifactTransferException(download.getArtifact(), group.repository, e)); 484 } 485 } 486 487 evaluateDownloads(session, group); 488 } 489 490 private List<ArtifactDownload> gatherDownloads(RepositorySystemSession session, ResolutionGroup group) { 491 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 492 List<ArtifactDownload> downloads = new ArrayList<>(); 493 494 for (ResolutionItem item : group.items) { 495 Artifact artifact = item.artifact; 496 497 if (item.resolved.get()) { 498 // resolved in previous resolution group 499 continue; 500 } 501 502 ArtifactDownload download = new ArtifactDownload(); 503 download.setArtifact(artifact); 504 download.setRequestContext(item.request.getRequestContext()); 505 download.setListener(SafeTransferListener.wrap(session)); 506 download.setTrace(item.trace); 507 if (item.local.getPath() != null) { 508 download.setPath(item.local.getPath()); 509 download.setExistenceCheck(true); 510 } else { 511 String path = 512 lrm.getPathForRemoteArtifact(artifact, group.repository, item.request.getRequestContext()); 513 download.setPath(lrm.getRepository().getBasePath().resolve(path)); 514 } 515 516 boolean snapshot = artifact.isSnapshot(); 517 RepositoryPolicy policy = remoteRepositoryManager.getPolicy(session, group.repository, !snapshot, snapshot); 518 519 int errorPolicy = Utils.getPolicy(session, artifact, group.repository); 520 if ((errorPolicy & ResolutionErrorPolicy.CACHE_ALL) != 0) { 521 UpdateCheck<Artifact, ArtifactTransferException> check = new UpdateCheck<>(); 522 check.setItem(artifact); 523 check.setPath(download.getPath()); 524 check.setFileValid(false); 525 check.setRepository(group.repository); 526 check.setArtifactPolicy(policy.getArtifactUpdatePolicy()); 527 check.setMetadataPolicy(policy.getMetadataUpdatePolicy()); 528 item.updateCheck = check; 529 updateCheckManager.checkArtifact(session, check); 530 if (!check.isRequired()) { 531 item.result.addException(group.repository, check.getException()); 532 continue; 533 } 534 } 535 536 download.setChecksumPolicy(policy.getChecksumPolicy()); 537 download.setRepositories(item.repository.getMirroredRepositories()); 538 downloads.add(download); 539 item.download = download; 540 } 541 542 return downloads; 543 } 544 545 private void evaluateDownloads(RepositorySystemSession session, ResolutionGroup group) { 546 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 547 548 for (ResolutionItem item : group.items) { 549 ArtifactDownload download = item.download; 550 if (download == null) { 551 continue; 552 } 553 554 Artifact artifact = download.getArtifact(); 555 if (download.getException() == null) { 556 item.resolved.set(true); 557 item.result.setRepository(group.repository); 558 try { 559 artifact = artifact.setPath(getPath(session, artifact, download.getPath())); 560 item.result.setArtifact(artifact); 561 562 lrm.add( 563 session, 564 new LocalArtifactRegistration(artifact, group.repository, download.getSupportedContexts())); 565 } catch (ArtifactTransferException e) { 566 download.setException(e); 567 item.result.addException(group.repository, e); 568 } 569 } else { 570 item.result.addException(group.repository, download.getException()); 571 } 572 573 /* 574 * NOTE: Touch after registration with local repo to ensure concurrent resolution is not rejected with 575 * "already updated" via session data when actual update to local repo is still pending. 576 */ 577 if (item.updateCheck != null) { 578 item.updateCheck.setException(download.getException()); 579 updateCheckManager.touchArtifact(session, item.updateCheck); 580 } 581 582 artifactDownloaded(session, download.getTrace(), artifact, group.repository, download.getException()); 583 if (download.getException() == null) { 584 artifactResolved(session, download.getTrace(), artifact, group.repository, null); 585 } 586 } 587 } 588 589 private void artifactResolving(RepositorySystemSession session, RequestTrace trace, Artifact artifact) { 590 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_RESOLVING); 591 event.setTrace(trace); 592 event.setArtifact(artifact); 593 594 repositoryEventDispatcher.dispatch(event.build()); 595 } 596 597 private void artifactResolved( 598 RepositorySystemSession session, 599 RequestTrace trace, 600 Artifact artifact, 601 ArtifactRepository repository, 602 Collection<Exception> exceptions) { 603 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_RESOLVED); 604 event.setTrace(trace); 605 event.setArtifact(artifact); 606 event.setRepository(repository); 607 event.setExceptions(exceptions != null ? new ArrayList<>(exceptions) : null); 608 if (artifact != null) { 609 event.setPath(artifact.getPath()); 610 } 611 612 repositoryEventDispatcher.dispatch(event.build()); 613 } 614 615 private void artifactDownloading( 616 RepositorySystemSession session, RequestTrace trace, Artifact artifact, RemoteRepository repository) { 617 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DOWNLOADING); 618 event.setTrace(trace); 619 event.setArtifact(artifact); 620 event.setRepository(repository); 621 622 repositoryEventDispatcher.dispatch(event.build()); 623 } 624 625 private void artifactDownloaded( 626 RepositorySystemSession session, 627 RequestTrace trace, 628 Artifact artifact, 629 RemoteRepository repository, 630 Exception exception) { 631 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DOWNLOADED); 632 event.setTrace(trace); 633 event.setArtifact(artifact); 634 event.setRepository(repository); 635 event.setException(exception); 636 if (artifact != null) { 637 event.setPath(artifact.getPath()); 638 } 639 640 repositoryEventDispatcher.dispatch(event.build()); 641 } 642 643 static class ResolutionGroup { 644 645 final RemoteRepository repository; 646 647 final List<ResolutionItem> items = new ArrayList<>(); 648 649 ResolutionGroup(RemoteRepository repository) { 650 this.repository = repository; 651 } 652 653 boolean matches(RemoteRepository repo) { 654 return repository.getUrl().equals(repo.getUrl()) 655 && repository.getContentType().equals(repo.getContentType()) 656 && repository.isRepositoryManager() == repo.isRepositoryManager(); 657 } 658 } 659 660 static class ResolutionItem { 661 662 final RequestTrace trace; 663 664 final ArtifactRequest request; 665 666 final ArtifactResult result; 667 668 final LocalArtifactResult local; 669 670 final RemoteRepository repository; 671 672 final Artifact artifact; 673 674 final AtomicBoolean resolved; 675 676 ArtifactDownload download; 677 678 UpdateCheck<Artifact, ArtifactTransferException> updateCheck; 679 680 ResolutionItem( 681 RequestTrace trace, 682 Artifact artifact, 683 AtomicBoolean resolved, 684 ArtifactResult result, 685 LocalArtifactResult local, 686 RemoteRepository repository) { 687 this.trace = trace; 688 this.artifact = artifact; 689 this.resolved = resolved; 690 this.result = result; 691 this.request = result.getRequest(); 692 this.local = local; 693 this.repository = repository; 694 } 695 } 696}