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