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