001package org.eclipse.aether.internal.impl;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import javax.inject.Inject;
023import javax.inject.Named;
024import javax.inject.Singleton;
025
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.List;
029import java.util.concurrent.atomic.AtomicBoolean;
030
031import org.eclipse.aether.RepositorySystem;
032import org.eclipse.aether.RepositorySystemSession;
033import org.eclipse.aether.RequestTrace;
034import org.eclipse.aether.SyncContext;
035import org.eclipse.aether.artifact.Artifact;
036import org.eclipse.aether.collection.CollectRequest;
037import org.eclipse.aether.collection.CollectResult;
038import org.eclipse.aether.collection.DependencyCollectionException;
039import org.eclipse.aether.deployment.DeployRequest;
040import org.eclipse.aether.deployment.DeployResult;
041import org.eclipse.aether.deployment.DeploymentException;
042import org.eclipse.aether.graph.DependencyFilter;
043import org.eclipse.aether.graph.DependencyVisitor;
044import org.eclipse.aether.impl.ArtifactDescriptorReader;
045import org.eclipse.aether.impl.ArtifactResolver;
046import org.eclipse.aether.impl.DependencyCollector;
047import org.eclipse.aether.impl.Deployer;
048import org.eclipse.aether.impl.Installer;
049import org.eclipse.aether.impl.LocalRepositoryProvider;
050import org.eclipse.aether.impl.MetadataResolver;
051import org.eclipse.aether.impl.RemoteRepositoryManager;
052import org.eclipse.aether.impl.RepositorySystemLifecycle;
053import org.eclipse.aether.impl.VersionRangeResolver;
054import org.eclipse.aether.impl.VersionResolver;
055import org.eclipse.aether.installation.InstallRequest;
056import org.eclipse.aether.installation.InstallResult;
057import org.eclipse.aether.installation.InstallationException;
058import org.eclipse.aether.repository.Authentication;
059import org.eclipse.aether.repository.LocalRepository;
060import org.eclipse.aether.repository.LocalRepositoryManager;
061import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
062import org.eclipse.aether.repository.Proxy;
063import org.eclipse.aether.repository.RemoteRepository;
064import org.eclipse.aether.resolution.ArtifactDescriptorException;
065import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
066import org.eclipse.aether.resolution.ArtifactDescriptorResult;
067import org.eclipse.aether.resolution.ArtifactRequest;
068import org.eclipse.aether.resolution.ArtifactResolutionException;
069import org.eclipse.aether.resolution.ArtifactResult;
070import org.eclipse.aether.resolution.DependencyRequest;
071import org.eclipse.aether.resolution.DependencyResolutionException;
072import org.eclipse.aether.resolution.DependencyResult;
073import org.eclipse.aether.resolution.MetadataRequest;
074import org.eclipse.aether.resolution.MetadataResult;
075import org.eclipse.aether.resolution.VersionRangeRequest;
076import org.eclipse.aether.resolution.VersionRangeResolutionException;
077import org.eclipse.aether.resolution.VersionRangeResult;
078import org.eclipse.aether.resolution.VersionRequest;
079import org.eclipse.aether.resolution.VersionResolutionException;
080import org.eclipse.aether.resolution.VersionResult;
081import org.eclipse.aether.spi.locator.Service;
082import org.eclipse.aether.spi.locator.ServiceLocator;
083import org.eclipse.aether.spi.synccontext.SyncContextFactory;
084import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor;
085import org.eclipse.aether.util.graph.visitor.TreeDependencyVisitor;
086
087import static java.util.Objects.requireNonNull;
088
089/**
090 *
091 */
092@Singleton
093@Named
094public class DefaultRepositorySystem
095        implements RepositorySystem, Service
096{
097    private final AtomicBoolean shutdown;
098
099    private VersionResolver versionResolver;
100
101    private VersionRangeResolver versionRangeResolver;
102
103    private ArtifactResolver artifactResolver;
104
105    private MetadataResolver metadataResolver;
106
107    private ArtifactDescriptorReader artifactDescriptorReader;
108
109    private DependencyCollector dependencyCollector;
110
111    private Installer installer;
112
113    private Deployer deployer;
114
115    private LocalRepositoryProvider localRepositoryProvider;
116
117    private SyncContextFactory syncContextFactory;
118
119    private RemoteRepositoryManager remoteRepositoryManager;
120
121    private RepositorySystemLifecycle repositorySystemLifecycle;
122
123    public DefaultRepositorySystem()
124    {
125        // enables default constructor
126        this.shutdown = new AtomicBoolean( false );
127    }
128
129    @SuppressWarnings( "checkstyle:parameternumber" )
130    @Inject
131    DefaultRepositorySystem( VersionResolver versionResolver, VersionRangeResolver versionRangeResolver,
132                             ArtifactResolver artifactResolver, MetadataResolver metadataResolver,
133                             ArtifactDescriptorReader artifactDescriptorReader,
134                             DependencyCollector dependencyCollector, Installer installer, Deployer deployer,
135                             LocalRepositoryProvider localRepositoryProvider, SyncContextFactory syncContextFactory,
136                             RemoteRepositoryManager remoteRepositoryManager,
137                             RepositorySystemLifecycle repositorySystemLifecycle )
138    {
139        this.shutdown = new AtomicBoolean( false );
140        setVersionResolver( versionResolver );
141        setVersionRangeResolver( versionRangeResolver );
142        setArtifactResolver( artifactResolver );
143        setMetadataResolver( metadataResolver );
144        setArtifactDescriptorReader( artifactDescriptorReader );
145        setDependencyCollector( dependencyCollector );
146        setInstaller( installer );
147        setDeployer( deployer );
148        setLocalRepositoryProvider( localRepositoryProvider );
149        setSyncContextFactory( syncContextFactory );
150        setRemoteRepositoryManager( remoteRepositoryManager );
151        setRepositorySystemLifecycle( repositorySystemLifecycle );
152    }
153
154    @Override
155    public void initService( ServiceLocator locator )
156    {
157        setVersionResolver( locator.getService( VersionResolver.class ) );
158        setVersionRangeResolver( locator.getService( VersionRangeResolver.class ) );
159        setArtifactResolver( locator.getService( ArtifactResolver.class ) );
160        setMetadataResolver( locator.getService( MetadataResolver.class ) );
161        setArtifactDescriptorReader( locator.getService( ArtifactDescriptorReader.class ) );
162        setDependencyCollector( locator.getService( DependencyCollector.class ) );
163        setInstaller( locator.getService( Installer.class ) );
164        setDeployer( locator.getService( Deployer.class ) );
165        setLocalRepositoryProvider( locator.getService( LocalRepositoryProvider.class ) );
166        setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) );
167        setSyncContextFactory( locator.getService( SyncContextFactory.class ) );
168        setRepositorySystemLifecycle( locator.getService( RepositorySystemLifecycle.class ) );
169    }
170
171    /**
172     * @deprecated not used any more since MRESOLVER-36 move to slf4j, added back in MRESOLVER-64 for compatibility
173     */
174    @Deprecated
175    public DefaultRepositorySystem setLoggerFactory( org.eclipse.aether.spi.log.LoggerFactory loggerFactory )
176    {
177        // this.logger = NullLoggerFactory.getSafeLogger( loggerFactory, getClass() );
178        return this;
179    }
180
181    public DefaultRepositorySystem setVersionResolver( VersionResolver versionResolver )
182    {
183        this.versionResolver = requireNonNull( versionResolver, "version resolver cannot be null" );
184        return this;
185    }
186
187    public DefaultRepositorySystem setVersionRangeResolver( VersionRangeResolver versionRangeResolver )
188    {
189        this.versionRangeResolver = requireNonNull(
190                versionRangeResolver, "version range resolver cannot be null" );
191        return this;
192    }
193
194    public DefaultRepositorySystem setArtifactResolver( ArtifactResolver artifactResolver )
195    {
196        this.artifactResolver = requireNonNull( artifactResolver, "artifact resolver cannot be null" );
197        return this;
198    }
199
200    public DefaultRepositorySystem setMetadataResolver( MetadataResolver metadataResolver )
201    {
202        this.metadataResolver = requireNonNull( metadataResolver, "metadata resolver cannot be null" );
203        return this;
204    }
205
206    public DefaultRepositorySystem setArtifactDescriptorReader( ArtifactDescriptorReader artifactDescriptorReader )
207    {
208        this.artifactDescriptorReader = requireNonNull(
209                artifactDescriptorReader, "artifact descriptor reader cannot be null" );
210        return this;
211    }
212
213    public DefaultRepositorySystem setDependencyCollector( DependencyCollector dependencyCollector )
214    {
215        this.dependencyCollector = requireNonNull( dependencyCollector, "dependency collector cannot be null" );
216        return this;
217    }
218
219    public DefaultRepositorySystem setInstaller( Installer installer )
220    {
221        this.installer = requireNonNull( installer, "installer cannot be null" );
222        return this;
223    }
224
225    public DefaultRepositorySystem setDeployer( Deployer deployer )
226    {
227        this.deployer = requireNonNull( deployer, "deployer cannot be null" );
228        return this;
229    }
230
231    public DefaultRepositorySystem setLocalRepositoryProvider( LocalRepositoryProvider localRepositoryProvider )
232    {
233        this.localRepositoryProvider = requireNonNull(
234                localRepositoryProvider, "local repository provider cannot be null" );
235        return this;
236    }
237
238    public DefaultRepositorySystem setSyncContextFactory( SyncContextFactory syncContextFactory )
239    {
240        this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" );
241        return this;
242    }
243
244    public DefaultRepositorySystem setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager )
245    {
246        this.remoteRepositoryManager = requireNonNull(
247                remoteRepositoryManager, "remote repository provider cannot be null" );
248        return this;
249    }
250
251    public DefaultRepositorySystem setRepositorySystemLifecycle( RepositorySystemLifecycle repositorySystemLifecycle )
252    {
253        this.repositorySystemLifecycle = requireNonNull(
254                repositorySystemLifecycle, "repository system lifecycle cannot be null" );
255        return this;
256    }
257
258    @Override
259    public VersionResult resolveVersion( RepositorySystemSession session, VersionRequest request )
260            throws VersionResolutionException
261    {
262        validateSession( session );
263        requireNonNull( request, "request cannot be null" );
264
265        return versionResolver.resolveVersion( session, request );
266    }
267
268    @Override
269    public VersionRangeResult resolveVersionRange( RepositorySystemSession session, VersionRangeRequest request )
270            throws VersionRangeResolutionException
271    {
272        validateSession( session );
273        requireNonNull( request, "request cannot be null" );
274
275        return versionRangeResolver.resolveVersionRange( session, request );
276    }
277
278    @Override
279    public ArtifactDescriptorResult readArtifactDescriptor( RepositorySystemSession session,
280                                                            ArtifactDescriptorRequest request )
281            throws ArtifactDescriptorException
282    {
283        validateSession( session );
284        requireNonNull( request, "request cannot be null" );
285
286        return artifactDescriptorReader.readArtifactDescriptor( session, request );
287    }
288
289    @Override
290    public ArtifactResult resolveArtifact( RepositorySystemSession session, ArtifactRequest request )
291            throws ArtifactResolutionException
292    {
293        validateSession( session );
294        requireNonNull( session, "session cannot be null" );
295
296        return artifactResolver.resolveArtifact( session, request );
297    }
298
299    @Override
300    public List<ArtifactResult> resolveArtifacts( RepositorySystemSession session,
301                                                  Collection<? extends ArtifactRequest> requests )
302            throws ArtifactResolutionException
303    {
304        validateSession( session );
305        requireNonNull( requests, "requests cannot be null" );
306
307        return artifactResolver.resolveArtifacts( session, requests );
308    }
309
310    @Override
311    public List<MetadataResult> resolveMetadata( RepositorySystemSession session,
312                                                 Collection<? extends MetadataRequest> requests )
313    {
314        validateSession( session );
315        requireNonNull( requests, "requests cannot be null" );
316
317        return metadataResolver.resolveMetadata( session, requests );
318    }
319
320    @Override
321    public CollectResult collectDependencies( RepositorySystemSession session, CollectRequest request )
322            throws DependencyCollectionException
323    {
324        validateSession( session );
325        requireNonNull( request, "request cannot be null" );
326
327        return dependencyCollector.collectDependencies( session, request );
328    }
329
330    @Override
331    public DependencyResult resolveDependencies( RepositorySystemSession session, DependencyRequest request )
332            throws DependencyResolutionException
333    {
334        validateSession( session );
335        requireNonNull( request, "request cannot be null" );
336
337        RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );
338
339        DependencyResult result = new DependencyResult( request );
340
341        DependencyCollectionException dce = null;
342        ArtifactResolutionException are = null;
343
344        if ( request.getRoot() != null )
345        {
346            result.setRoot( request.getRoot() );
347        }
348        else if ( request.getCollectRequest() != null )
349        {
350            CollectResult collectResult;
351            try
352            {
353                request.getCollectRequest().setTrace( trace );
354                collectResult = dependencyCollector.collectDependencies( session, request.getCollectRequest() );
355            }
356            catch ( DependencyCollectionException e )
357            {
358                dce = e;
359                collectResult = e.getResult();
360            }
361            result.setRoot( collectResult.getRoot() );
362            result.setCycles( collectResult.getCycles() );
363            result.setCollectExceptions( collectResult.getExceptions() );
364        }
365        else
366        {
367            throw new NullPointerException( "dependency node and collect request cannot be null" );
368        }
369
370        ArtifactRequestBuilder builder = new ArtifactRequestBuilder( trace );
371        DependencyFilter filter = request.getFilter();
372        DependencyVisitor visitor = ( filter != null ) ? new FilteringDependencyVisitor( builder, filter ) : builder;
373        visitor = new TreeDependencyVisitor( visitor );
374
375        if ( result.getRoot() != null )
376        {
377            result.getRoot().accept( visitor );
378        }
379
380        List<ArtifactRequest> requests = builder.getRequests();
381
382        List<ArtifactResult> results;
383        try
384        {
385            results = artifactResolver.resolveArtifacts( session, requests );
386        }
387        catch ( ArtifactResolutionException e )
388        {
389            are = e;
390            results = e.getResults();
391        }
392        result.setArtifactResults( results );
393
394        updateNodesWithResolvedArtifacts( results );
395
396        if ( dce != null )
397        {
398            throw new DependencyResolutionException( result, dce );
399        }
400        else if ( are != null )
401        {
402            throw new DependencyResolutionException( result, are );
403        }
404
405        return result;
406    }
407
408    private void updateNodesWithResolvedArtifacts( List<ArtifactResult> results )
409    {
410        for ( ArtifactResult result : results )
411        {
412            Artifact artifact = result.getArtifact();
413            if ( artifact != null )
414            {
415                result.getRequest().getDependencyNode().setArtifact( artifact );
416            }
417        }
418    }
419
420    @Override
421    public InstallResult install( RepositorySystemSession session, InstallRequest request )
422            throws InstallationException
423    {
424        validateSession( session );
425        requireNonNull( request, "request cannot be null" );
426
427        return installer.install( session, request );
428    }
429
430    @Override
431    public DeployResult deploy( RepositorySystemSession session, DeployRequest request )
432            throws DeploymentException
433    {
434        validateSession( session );
435        requireNonNull( request, "request cannot be null" );
436
437        return deployer.deploy( session, request );
438    }
439
440    @Override
441    public LocalRepositoryManager newLocalRepositoryManager( RepositorySystemSession session,
442                                                             LocalRepository localRepository )
443    {
444        requireNonNull( session, "session cannot be null" );
445        requireNonNull( localRepository, "localRepository cannot be null" );
446
447        try
448        {
449            return localRepositoryProvider.newLocalRepositoryManager( session, localRepository );
450        }
451        catch ( NoLocalRepositoryManagerException e )
452        {
453            throw new IllegalArgumentException( e.getMessage(), e );
454        }
455    }
456
457    @Override
458    public SyncContext newSyncContext( RepositorySystemSession session, boolean shared )
459    {
460        validateSession( session );
461        return syncContextFactory.newInstance( session, shared );
462    }
463
464    @Override
465    public List<RemoteRepository> newResolutionRepositories( RepositorySystemSession session,
466                                                             List<RemoteRepository> repositories )
467    {
468        validateSession( session );
469        validateRepositories( repositories );
470
471        repositories =
472                remoteRepositoryManager.aggregateRepositories( session, new ArrayList<RemoteRepository>(), repositories,
473                        true );
474        return repositories;
475    }
476
477    @Override
478    public RemoteRepository newDeploymentRepository( RepositorySystemSession session, RemoteRepository repository )
479    {
480        validateSession( session );
481        requireNonNull( repository, "repository cannot be null" );
482
483        RemoteRepository.Builder builder = new RemoteRepository.Builder( repository );
484        Authentication auth = session.getAuthenticationSelector().getAuthentication( repository );
485        builder.setAuthentication( auth );
486        Proxy proxy = session.getProxySelector().getProxy( repository );
487        builder.setProxy( proxy );
488        return builder.build();
489    }
490
491    @Override
492    public void addOnSystemEndedHandler( Runnable handler )
493    {
494        repositorySystemLifecycle.addOnSystemEndedHandler( handler );
495    }
496
497    @Override
498    public void shutdown()
499    {
500        if ( shutdown.compareAndSet( false, true ) )
501        {
502            repositorySystemLifecycle.systemEnded();
503        }
504    }
505
506    private void validateSession( RepositorySystemSession session )
507    {
508        requireNonNull( session, "repository system session cannot be null" );
509        invalidSession( session.getLocalRepositoryManager(), "local repository manager" );
510        invalidSession( session.getSystemProperties(), "system properties" );
511        invalidSession( session.getUserProperties(), "user properties" );
512        invalidSession( session.getConfigProperties(), "config properties" );
513        invalidSession( session.getMirrorSelector(), "mirror selector" );
514        invalidSession( session.getProxySelector(), "proxy selector" );
515        invalidSession( session.getAuthenticationSelector(), "authentication selector" );
516        invalidSession( session.getArtifactTypeRegistry(), "artifact type registry" );
517        invalidSession( session.getData(), "data" );
518        if ( shutdown.get() )
519        {
520            throw new IllegalStateException( "repository system is already shut down" );
521        }
522    }
523
524    private void validateRepositories( List<RemoteRepository> repositories )
525    {
526        requireNonNull( repositories, "repositories cannot be null" );
527        for ( RemoteRepository repository : repositories )
528        {
529            requireNonNull( repository, "repository cannot be null" );
530        }
531    }
532
533    private void invalidSession( Object obj, String name )
534    {
535        requireNonNull( obj, "repository system session's " + name + " cannot be null" );
536    }
537}