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