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    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}