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