View Javadoc
1   package org.eclipse.aether.internal.impl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   * 
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.Iterator;
28  import java.util.List;
29  import static java.util.Objects.requireNonNull;
30  import java.util.concurrent.atomic.AtomicBoolean;
31  
32  import javax.inject.Inject;
33  import javax.inject.Named;
34  
35  import org.eclipse.aether.RepositoryEvent;
36  import org.eclipse.aether.RepositoryEvent.EventType;
37  import org.eclipse.aether.RepositorySystemSession;
38  import org.eclipse.aether.RequestTrace;
39  import org.eclipse.aether.SyncContext;
40  import org.eclipse.aether.artifact.Artifact;
41  import org.eclipse.aether.artifact.ArtifactProperties;
42  import org.eclipse.aether.impl.ArtifactResolver;
43  import org.eclipse.aether.impl.OfflineController;
44  import org.eclipse.aether.impl.RemoteRepositoryManager;
45  import org.eclipse.aether.impl.RepositoryConnectorProvider;
46  import org.eclipse.aether.impl.RepositoryEventDispatcher;
47  import org.eclipse.aether.impl.SyncContextFactory;
48  import org.eclipse.aether.impl.UpdateCheck;
49  import org.eclipse.aether.impl.UpdateCheckManager;
50  import org.eclipse.aether.impl.VersionResolver;
51  import org.eclipse.aether.repository.ArtifactRepository;
52  import org.eclipse.aether.repository.LocalArtifactRegistration;
53  import org.eclipse.aether.repository.LocalArtifactRequest;
54  import org.eclipse.aether.repository.LocalArtifactResult;
55  import org.eclipse.aether.repository.LocalRepository;
56  import org.eclipse.aether.repository.LocalRepositoryManager;
57  import org.eclipse.aether.repository.RemoteRepository;
58  import org.eclipse.aether.repository.RepositoryPolicy;
59  import org.eclipse.aether.repository.WorkspaceReader;
60  import org.eclipse.aether.resolution.ArtifactRequest;
61  import org.eclipse.aether.resolution.ArtifactResolutionException;
62  import org.eclipse.aether.resolution.ArtifactResult;
63  import org.eclipse.aether.resolution.ResolutionErrorPolicy;
64  import org.eclipse.aether.resolution.VersionRequest;
65  import org.eclipse.aether.resolution.VersionResolutionException;
66  import org.eclipse.aether.resolution.VersionResult;
67  import org.eclipse.aether.spi.connector.ArtifactDownload;
68  import org.eclipse.aether.spi.connector.RepositoryConnector;
69  import org.eclipse.aether.spi.io.FileProcessor;
70  import org.eclipse.aether.spi.locator.Service;
71  import org.eclipse.aether.spi.locator.ServiceLocator;
72  import org.eclipse.aether.transfer.ArtifactNotFoundException;
73  import org.eclipse.aether.transfer.ArtifactTransferException;
74  import org.eclipse.aether.transfer.NoRepositoryConnectorException;
75  import org.eclipse.aether.transfer.RepositoryOfflineException;
76  import org.eclipse.aether.util.ConfigUtils;
77  import org.slf4j.Logger;
78  import org.slf4j.LoggerFactory;
79  
80  /**
81   */
82  @Named
83  public class DefaultArtifactResolver
84      implements ArtifactResolver, Service
85  {
86  
87      private static final String CONFIG_PROP_SNAPSHOT_NORMALIZATION = "aether.artifactResolver.snapshotNormalization";
88  
89      private static final Logger LOGGER = LoggerFactory.getLogger( DefaultArtifactResolver.class );
90  
91      private FileProcessor fileProcessor;
92  
93      private RepositoryEventDispatcher repositoryEventDispatcher;
94  
95      private VersionResolver versionResolver;
96  
97      private UpdateCheckManager updateCheckManager;
98  
99      private RepositoryConnectorProvider repositoryConnectorProvider;
100 
101     private RemoteRepositoryManager remoteRepositoryManager;
102 
103     private SyncContextFactory syncContextFactory;
104 
105     private OfflineController offlineController;
106 
107     public DefaultArtifactResolver()
108     {
109         // enables default constructor
110     }
111 
112     @Inject
113     DefaultArtifactResolver( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher,
114                              VersionResolver versionResolver, UpdateCheckManager updateCheckManager,
115                              RepositoryConnectorProvider repositoryConnectorProvider,
116                              RemoteRepositoryManager remoteRepositoryManager, SyncContextFactory syncContextFactory,
117                              OfflineController offlineController )
118     {
119         setFileProcessor( fileProcessor );
120         setRepositoryEventDispatcher( repositoryEventDispatcher );
121         setVersionResolver( versionResolver );
122         setUpdateCheckManager( updateCheckManager );
123         setRepositoryConnectorProvider( repositoryConnectorProvider );
124         setRemoteRepositoryManager( remoteRepositoryManager );
125         setSyncContextFactory( syncContextFactory );
126         setOfflineController( offlineController );
127     }
128 
129     public void initService( ServiceLocator locator )
130     {
131         setFileProcessor( locator.getService( FileProcessor.class ) );
132         setRepositoryEventDispatcher( locator.getService( RepositoryEventDispatcher.class ) );
133         setVersionResolver( locator.getService( VersionResolver.class ) );
134         setUpdateCheckManager( locator.getService( UpdateCheckManager.class ) );
135         setRepositoryConnectorProvider( locator.getService( RepositoryConnectorProvider.class ) );
136         setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) );
137         setSyncContextFactory( locator.getService( SyncContextFactory.class ) );
138         setOfflineController( locator.getService( OfflineController.class ) );
139     }
140 
141     public DefaultArtifactResolver setFileProcessor( FileProcessor fileProcessor )
142     {
143         this.fileProcessor = requireNonNull( fileProcessor, "file processor cannot be null" );
144         return this;
145     }
146 
147     public DefaultArtifactResolver setRepositoryEventDispatcher( RepositoryEventDispatcher repositoryEventDispatcher )
148     {
149         this.repositoryEventDispatcher = requireNonNull( repositoryEventDispatcher, "repository event dispatcher cannot be null" );
150         return this;
151     }
152 
153     public DefaultArtifactResolver setVersionResolver( VersionResolver versionResolver )
154     {
155         this.versionResolver = requireNonNull( versionResolver, "version resolver cannot be null" );
156         return this;
157     }
158 
159     public DefaultArtifactResolver setUpdateCheckManager( UpdateCheckManager updateCheckManager )
160     {
161         this.updateCheckManager = requireNonNull( updateCheckManager, "update check manager cannot be null" );
162         return this;
163     }
164 
165     public DefaultArtifactResolver setRepositoryConnectorProvider( RepositoryConnectorProvider repositoryConnectorProvider )
166     {
167         this.repositoryConnectorProvider = requireNonNull( repositoryConnectorProvider, "repository connector provider cannot be null" );
168         return this;
169     }
170 
171     public DefaultArtifactResolver setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager )
172     {
173         this.remoteRepositoryManager = requireNonNull( remoteRepositoryManager, "remote repository provider cannot be null" );
174         return this;
175     }
176 
177     public DefaultArtifactResolver setSyncContextFactory( SyncContextFactory syncContextFactory )
178     {
179         this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" );
180         return this;
181     }
182 
183     public DefaultArtifactResolver setOfflineController( OfflineController offlineController )
184     {
185         this.offlineController = requireNonNull( offlineController, "offline controller cannot be null" );
186         return this;
187     }
188 
189     public ArtifactResult resolveArtifact( RepositorySystemSession session, ArtifactRequest request )
190         throws ArtifactResolutionException
191     {
192         return resolveArtifacts( session, Collections.singleton( request ) ).get( 0 );
193     }
194 
195     public List<ArtifactResult> resolveArtifacts( RepositorySystemSession session,
196                                                   Collection<? extends ArtifactRequest> requests )
197         throws ArtifactResolutionException
198     {
199         SyncContext syncContext = syncContextFactory.newInstance( session, false );
200 
201         try
202         {
203             Collection<Artifact> artifacts = new ArrayList<Artifact>( requests.size() );
204             for ( ArtifactRequest request : requests )
205             {
206                 if ( request.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null )
207                 {
208                     continue;
209                 }
210                 artifacts.add( request.getArtifact() );
211             }
212 
213             syncContext.acquire( artifacts, null );
214 
215             return resolve( session, requests );
216         }
217         finally
218         {
219             syncContext.close();
220         }
221     }
222 
223     private List<ArtifactResult> resolve( RepositorySystemSession session,
224                                           Collection<? extends ArtifactRequest> requests )
225         throws ArtifactResolutionException
226     {
227         List<ArtifactResult> results = new ArrayList<ArtifactResult>( requests.size() );
228         boolean failures = false;
229 
230         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
231         WorkspaceReader workspace = session.getWorkspaceReader();
232 
233         List<ResolutionGroup> groups = new ArrayList<ResolutionGroup>();
234 
235         for ( ArtifactRequest request : requests )
236         {
237             RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );
238 
239             ArtifactResult result = new ArtifactResult( request );
240             results.add( result );
241 
242             Artifact artifact = request.getArtifact();
243             List<RemoteRepository> repos = request.getRepositories();
244 
245             artifactResolving( session, trace, artifact );
246 
247             String localPath = artifact.getProperty( ArtifactProperties.LOCAL_PATH, null );
248             if ( localPath != null )
249             {
250                 // unhosted artifact, just validate file
251                 File file = new File( localPath );
252                 if ( !file.isFile() )
253                 {
254                     failures = true;
255                     result.addException( new ArtifactNotFoundException( artifact, null ) );
256                 }
257                 else
258                 {
259                     artifact = artifact.setFile( file );
260                     result.setArtifact( artifact );
261                     artifactResolved( session, trace, artifact, null, result.getExceptions() );
262                 }
263                 continue;
264             }
265 
266             VersionResult versionResult;
267             try
268             {
269                 VersionRequest versionRequest = new VersionRequest( artifact, repos, request.getRequestContext() );
270                 versionRequest.setTrace( trace );
271                 versionResult = versionResolver.resolveVersion( session, versionRequest );
272             }
273             catch ( VersionResolutionException e )
274             {
275                 result.addException( e );
276                 continue;
277             }
278 
279             artifact = artifact.setVersion( versionResult.getVersion() );
280 
281             if ( versionResult.getRepository() != null )
282             {
283                 if ( versionResult.getRepository() instanceof RemoteRepository )
284                 {
285                     repos = Collections.singletonList( (RemoteRepository) versionResult.getRepository() );
286                 }
287                 else
288                 {
289                     repos = Collections.emptyList();
290                 }
291             }
292 
293             if ( workspace != null )
294             {
295                 File file = workspace.findArtifact( artifact );
296                 if ( file != null )
297                 {
298                     artifact = artifact.setFile( file );
299                     result.setArtifact( artifact );
300                     result.setRepository( workspace.getRepository() );
301                     artifactResolved( session, trace, artifact, result.getRepository(), null );
302                     continue;
303                 }
304             }
305 
306             LocalArtifactResult local =
307                 lrm.find( session, new LocalArtifactRequest( artifact, repos, request.getRequestContext() ) );
308             if ( isLocallyInstalled( local, versionResult ) )
309             {
310                 if ( local.getRepository() != null )
311                 {
312                     result.setRepository( local.getRepository() );
313                 }
314                 else
315                 {
316                     result.setRepository( lrm.getRepository() );
317                 }
318                 try
319                 {
320                     artifact = artifact.setFile( getFile( session, artifact, local.getFile() ) );
321                     result.setArtifact( artifact );
322                     artifactResolved( session, trace, artifact, result.getRepository(), null );
323                 }
324                 catch ( ArtifactTransferException e )
325                 {
326                     result.addException( e );
327                 }
328                 if ( !local.isAvailable() )
329                 {
330                     /*
331                      * NOTE: Interop with simple local repository: An artifact installed by a simple local repo manager
332                      * will not show up in the repository tracking file of the enhanced local repository. If however the
333                      * maven-metadata-local.xml tells us the artifact was installed locally, we sync the repository
334                      * tracking file.
335                      */
336                     lrm.add( session, new LocalArtifactRegistration( artifact ) );
337                 }
338                 continue;
339             }
340             else if ( local.getFile() != null )
341             {
342                 LOGGER.debug( "Verifying availability of {} from {}", local.getFile(), repos );
343             }
344 
345             AtomicBoolean resolved = new AtomicBoolean( false );
346             Iterator<ResolutionGroup> groupIt = groups.iterator();
347             for ( RemoteRepository repo : repos )
348             {
349                 if ( !repo.getPolicy( artifact.isSnapshot() ).isEnabled() )
350                 {
351                     continue;
352                 }
353 
354                 try
355                 {
356                     Utils.checkOffline( session, offlineController, repo );
357                 }
358                 catch ( RepositoryOfflineException e )
359                 {
360                     Exception exception =
361                         new ArtifactNotFoundException( artifact, repo, "Cannot access " + repo.getId() + " ("
362                             + repo.getUrl() + ") in offline mode and the artifact " + artifact
363                             + " has not been downloaded from it before.", e );
364                     result.addException( exception );
365                     continue;
366                 }
367 
368                 ResolutionGroup group = null;
369                 while ( groupIt.hasNext() )
370                 {
371                     ResolutionGroup t = groupIt.next();
372                     if ( t.matches( repo ) )
373                     {
374                         group = t;
375                         break;
376                     }
377                 }
378                 if ( group == null )
379                 {
380                     group = new ResolutionGroup( repo );
381                     groups.add( group );
382                     groupIt = Collections.<ResolutionGroup>emptyList().iterator();
383                 }
384                 group.items.add( new ResolutionItem( trace, artifact, resolved, result, local, repo ) );
385             }
386         }
387 
388         for ( ResolutionGroup group : groups )
389         {
390             performDownloads( session, group );
391         }
392 
393         for ( ArtifactResult result : results )
394         {
395             ArtifactRequest request = result.getRequest();
396 
397             Artifact artifact = result.getArtifact();
398             if ( artifact == null || artifact.getFile() == null )
399             {
400                 failures = true;
401                 if ( result.getExceptions().isEmpty() )
402                 {
403                     Exception exception = new ArtifactNotFoundException( request.getArtifact(), null );
404                     result.addException( 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         {
413             throw new ArtifactResolutionException( results );
414         }
415 
416         return results;
417     }
418 
419     private boolean isLocallyInstalled( LocalArtifactResult lar, VersionResult vr )
420     {
421         if ( lar.isAvailable() )
422         {
423             return true;
424         }
425         if ( lar.getFile() != null )
426         {
427             if ( vr.getRepository() instanceof LocalRepository )
428             {
429                 // resolution of (snapshot) version found locally installed artifact
430                 return true;
431             }
432             else if ( vr.getRepository() == null && lar.getRequest().getRepositories().isEmpty() )
433             {
434                 // resolution of version range found locally installed artifact
435                 return true;
436             }
437         }
438         return false;
439     }
440 
441     private File getFile( RepositorySystemSession session, Artifact artifact, File file )
442         throws ArtifactTransferException
443     {
444         if ( artifact.isSnapshot() && !artifact.getVersion().equals( artifact.getBaseVersion() )
445             && ConfigUtils.getBoolean( session, true, CONFIG_PROP_SNAPSHOT_NORMALIZATION ) )
446         {
447             String name = file.getName().replace( artifact.getVersion(), artifact.getBaseVersion() );
448             File dst = new File( file.getParent(), name );
449 
450             boolean copy = dst.length() != file.length() || dst.lastModified() != file.lastModified();
451             if ( copy )
452             {
453                 try
454                 {
455                     fileProcessor.copy( file, dst );
456                     dst.setLastModified( file.lastModified() );
457                 }
458                 catch ( IOException e )
459                 {
460                     throw new ArtifactTransferException( artifact, null, e );
461                 }
462             }
463 
464             file = dst;
465         }
466 
467         return file;
468     }
469 
470     private void performDownloads( RepositorySystemSession session, ResolutionGroup group )
471     {
472         List<ArtifactDownload> downloads = gatherDownloads( session, group );
473         if ( downloads.isEmpty() )
474         {
475             return;
476         }
477 
478         for ( ArtifactDownload download : downloads )
479         {
480             artifactDownloading( session, download.getTrace(), download.getArtifact(), group.repository );
481         }
482 
483         try
484         {
485             RepositoryConnector connector =
486                 repositoryConnectorProvider.newRepositoryConnector( session, group.repository );
487             try
488             {
489                 connector.get( downloads, null );
490             }
491             finally
492             {
493                 connector.close();
494             }
495         }
496         catch ( NoRepositoryConnectorException e )
497         {
498             for ( ArtifactDownload download : downloads )
499             {
500                 download.setException( new ArtifactTransferException( download.getArtifact(), group.repository, e ) );
501             }
502         }
503 
504         evaluateDownloads( session, group );
505     }
506 
507     private List<ArtifactDownload> gatherDownloads( RepositorySystemSession session, ResolutionGroup group )
508     {
509         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
510         List<ArtifactDownload> downloads = new ArrayList<ArtifactDownload>();
511 
512         for ( ResolutionItem item : group.items )
513         {
514             Artifact artifact = item.artifact;
515 
516             if ( item.resolved.get() )
517             {
518                 // resolved in previous resolution group
519                 continue;
520             }
521 
522             ArtifactDownload download = new ArtifactDownload();
523             download.setArtifact( artifact );
524             download.setRequestContext( item.request.getRequestContext() );
525             download.setListener( SafeTransferListener.wrap( session ) );
526             download.setTrace( item.trace );
527             if ( item.local.getFile() != null )
528             {
529                 download.setFile( item.local.getFile() );
530                 download.setExistenceCheck( true );
531             }
532             else
533             {
534                 String path =
535                     lrm.getPathForRemoteArtifact( artifact, group.repository, item.request.getRequestContext() );
536                 download.setFile( new File( lrm.getRepository().getBasedir(), path ) );
537             }
538 
539             boolean snapshot = artifact.isSnapshot();
540             RepositoryPolicy policy =
541                 remoteRepositoryManager.getPolicy( session, group.repository, !snapshot, snapshot );
542 
543             int errorPolicy = Utils.getPolicy( session, artifact, group.repository );
544             if ( ( errorPolicy & ResolutionErrorPolicy.CACHE_ALL ) != 0 )
545             {
546                 UpdateCheck<Artifact, ArtifactTransferException> check =
547                     new UpdateCheck<Artifact, ArtifactTransferException>();
548                 check.setItem( artifact );
549                 check.setFile( download.getFile() );
550                 check.setFileValid( false );
551                 check.setRepository( group.repository );
552                 check.setPolicy( policy.getUpdatePolicy() );
553                 item.updateCheck = check;
554                 updateCheckManager.checkArtifact( session, check );
555                 if ( !check.isRequired() )
556                 {
557                     item.result.addException( check.getException() );
558                     continue;
559                 }
560             }
561 
562             download.setChecksumPolicy( policy.getChecksumPolicy() );
563             download.setRepositories( item.repository.getMirroredRepositories() );
564             downloads.add( download );
565             item.download = download;
566         }
567 
568         return downloads;
569     }
570 
571     private void evaluateDownloads( RepositorySystemSession session, ResolutionGroup group )
572     {
573         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
574 
575         for ( ResolutionItem item : group.items )
576         {
577             ArtifactDownload download = item.download;
578             if ( download == null )
579             {
580                 continue;
581             }
582 
583             Artifact artifact = download.getArtifact();
584             if ( download.getException() == null )
585             {
586                 item.resolved.set( true );
587                 item.result.setRepository( group.repository );
588                 try
589                 {
590                     artifact = artifact.setFile( getFile( session, artifact, download.getFile() ) );
591                     item.result.setArtifact( artifact );
592 
593                     lrm.add( session,
594                              new LocalArtifactRegistration( artifact, group.repository, download.getSupportedContexts() ) );
595                 }
596                 catch ( ArtifactTransferException e )
597                 {
598                     download.setException( e );
599                     item.result.addException( e );
600                 }
601             }
602             else
603             {
604                 item.result.addException( download.getException() );
605             }
606 
607             /*
608              * NOTE: Touch after registration with local repo to ensure concurrent resolution is not rejected with
609              * "already updated" via session data when actual update to local repo is still pending.
610              */
611             if ( item.updateCheck != null )
612             {
613                 item.updateCheck.setException( download.getException() );
614                 updateCheckManager.touchArtifact( session, item.updateCheck );
615             }
616 
617             artifactDownloaded( session, download.getTrace(), artifact, group.repository, download.getException() );
618             if ( download.getException() == null )
619             {
620                 artifactResolved( session, download.getTrace(), artifact, group.repository, null );
621             }
622         }
623     }
624 
625     private void artifactResolving( RepositorySystemSession session, RequestTrace trace, Artifact artifact )
626     {
627         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_RESOLVING );
628         event.setTrace( trace );
629         event.setArtifact( artifact );
630 
631         repositoryEventDispatcher.dispatch( event.build() );
632     }
633 
634     private void artifactResolved( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
635                                    ArtifactRepository repository, List<Exception> exceptions )
636     {
637         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_RESOLVED );
638         event.setTrace( trace );
639         event.setArtifact( artifact );
640         event.setRepository( repository );
641         event.setExceptions( exceptions );
642         if ( artifact != null )
643         {
644             event.setFile( artifact.getFile() );
645         }
646 
647         repositoryEventDispatcher.dispatch( event.build() );
648     }
649 
650     private void artifactDownloading( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
651                                       RemoteRepository repository )
652     {
653         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DOWNLOADING );
654         event.setTrace( trace );
655         event.setArtifact( artifact );
656         event.setRepository( repository );
657 
658         repositoryEventDispatcher.dispatch( event.build() );
659     }
660 
661     private void artifactDownloaded( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
662                                      RemoteRepository repository, Exception exception )
663     {
664         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DOWNLOADED );
665         event.setTrace( trace );
666         event.setArtifact( artifact );
667         event.setRepository( repository );
668         event.setException( exception );
669         if ( artifact != null )
670         {
671             event.setFile( artifact.getFile() );
672         }
673 
674         repositoryEventDispatcher.dispatch( event.build() );
675     }
676 
677     static class ResolutionGroup
678     {
679 
680         final RemoteRepository repository;
681 
682         final List<ResolutionItem> items = new ArrayList<ResolutionItem>();
683 
684         ResolutionGroup( RemoteRepository repository )
685         {
686             this.repository = repository;
687         }
688 
689         boolean matches( RemoteRepository repo )
690         {
691             return repository.getUrl().equals( repo.getUrl() )
692                 && repository.getContentType().equals( repo.getContentType() )
693                 && repository.isRepositoryManager() == repo.isRepositoryManager();
694         }
695 
696     }
697 
698     static class ResolutionItem
699     {
700 
701         final RequestTrace trace;
702 
703         final ArtifactRequest request;
704 
705         final ArtifactResult result;
706 
707         final LocalArtifactResult local;
708 
709         final RemoteRepository repository;
710 
711         final Artifact artifact;
712 
713         final AtomicBoolean resolved;
714 
715         ArtifactDownload download;
716 
717         UpdateCheck<Artifact, ArtifactTransferException> updateCheck;
718 
719         ResolutionItem( RequestTrace trace, Artifact artifact, AtomicBoolean resolved, ArtifactResult result,
720                         LocalArtifactResult local, RemoteRepository repository )
721         {
722             this.trace = trace;
723             this.artifact = artifact;
724             this.resolved = resolved;
725             this.result = result;
726             this.request = result.getRequest();
727             this.local = local;
728             this.repository = repository;
729         }
730 
731     }
732 
733 }