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    public DefaultRepositorySystem() {
121        // enables default constructor
122        this.shutdown = new AtomicBoolean(false);
123    }
124
125    @SuppressWarnings("checkstyle:parameternumber")
126    @Inject
127    DefaultRepositorySystem(
128            VersionResolver versionResolver,
129            VersionRangeResolver versionRangeResolver,
130            ArtifactResolver artifactResolver,
131            MetadataResolver metadataResolver,
132            ArtifactDescriptorReader artifactDescriptorReader,
133            DependencyCollector dependencyCollector,
134            Installer installer,
135            Deployer deployer,
136            LocalRepositoryProvider localRepositoryProvider,
137            SyncContextFactory syncContextFactory,
138            RemoteRepositoryManager remoteRepositoryManager,
139            RepositorySystemLifecycle repositorySystemLifecycle) {
140        this.shutdown = new AtomicBoolean(false);
141        setVersionResolver(versionResolver);
142        setVersionRangeResolver(versionRangeResolver);
143        setArtifactResolver(artifactResolver);
144        setMetadataResolver(metadataResolver);
145        setArtifactDescriptorReader(artifactDescriptorReader);
146        setDependencyCollector(dependencyCollector);
147        setInstaller(installer);
148        setDeployer(deployer);
149        setLocalRepositoryProvider(localRepositoryProvider);
150        setSyncContextFactory(syncContextFactory);
151        setRemoteRepositoryManager(remoteRepositoryManager);
152        setRepositorySystemLifecycle(repositorySystemLifecycle);
153    }
154
155    @Override
156    public void initService(ServiceLocator locator) {
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        // this.logger = NullLoggerFactory.getSafeLogger( loggerFactory, getClass() );
177        return this;
178    }
179
180    public DefaultRepositorySystem setVersionResolver(VersionResolver versionResolver) {
181        this.versionResolver = requireNonNull(versionResolver, "version resolver cannot be null");
182        return this;
183    }
184
185    public DefaultRepositorySystem setVersionRangeResolver(VersionRangeResolver versionRangeResolver) {
186        this.versionRangeResolver = requireNonNull(versionRangeResolver, "version range resolver cannot be null");
187        return this;
188    }
189
190    public DefaultRepositorySystem setArtifactResolver(ArtifactResolver artifactResolver) {
191        this.artifactResolver = requireNonNull(artifactResolver, "artifact resolver cannot be null");
192        return this;
193    }
194
195    public DefaultRepositorySystem setMetadataResolver(MetadataResolver metadataResolver) {
196        this.metadataResolver = requireNonNull(metadataResolver, "metadata resolver cannot be null");
197        return this;
198    }
199
200    public DefaultRepositorySystem setArtifactDescriptorReader(ArtifactDescriptorReader artifactDescriptorReader) {
201        this.artifactDescriptorReader =
202                requireNonNull(artifactDescriptorReader, "artifact descriptor reader cannot be null");
203        return this;
204    }
205
206    public DefaultRepositorySystem setDependencyCollector(DependencyCollector dependencyCollector) {
207        this.dependencyCollector = requireNonNull(dependencyCollector, "dependency collector cannot be null");
208        return this;
209    }
210
211    public DefaultRepositorySystem setInstaller(Installer installer) {
212        this.installer = requireNonNull(installer, "installer cannot be null");
213        return this;
214    }
215
216    public DefaultRepositorySystem setDeployer(Deployer deployer) {
217        this.deployer = requireNonNull(deployer, "deployer cannot be null");
218        return this;
219    }
220
221    public DefaultRepositorySystem setLocalRepositoryProvider(LocalRepositoryProvider localRepositoryProvider) {
222        this.localRepositoryProvider =
223                requireNonNull(localRepositoryProvider, "local repository provider cannot be null");
224        return this;
225    }
226
227    public DefaultRepositorySystem setSyncContextFactory(SyncContextFactory syncContextFactory) {
228        this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null");
229        return this;
230    }
231
232    public DefaultRepositorySystem setRemoteRepositoryManager(RemoteRepositoryManager remoteRepositoryManager) {
233        this.remoteRepositoryManager =
234                requireNonNull(remoteRepositoryManager, "remote repository provider cannot be null");
235        return this;
236    }
237
238    public DefaultRepositorySystem setRepositorySystemLifecycle(RepositorySystemLifecycle repositorySystemLifecycle) {
239        this.repositorySystemLifecycle =
240                requireNonNull(repositorySystemLifecycle, "repository system lifecycle cannot be null");
241        return this;
242    }
243
244    @Override
245    public VersionResult resolveVersion(RepositorySystemSession session, VersionRequest request)
246            throws VersionResolutionException {
247        validateSession(session);
248        requireNonNull(request, "request cannot be null");
249
250        return versionResolver.resolveVersion(session, request);
251    }
252
253    @Override
254    public VersionRangeResult resolveVersionRange(RepositorySystemSession session, VersionRangeRequest request)
255            throws VersionRangeResolutionException {
256        validateSession(session);
257        requireNonNull(request, "request cannot be null");
258
259        return versionRangeResolver.resolveVersionRange(session, request);
260    }
261
262    @Override
263    public ArtifactDescriptorResult readArtifactDescriptor(
264            RepositorySystemSession session, ArtifactDescriptorRequest request) throws ArtifactDescriptorException {
265        validateSession(session);
266        requireNonNull(request, "request cannot be null");
267
268        return artifactDescriptorReader.readArtifactDescriptor(session, request);
269    }
270
271    @Override
272    public ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request)
273            throws ArtifactResolutionException {
274        validateSession(session);
275        requireNonNull(session, "session cannot be null");
276
277        return artifactResolver.resolveArtifact(session, request);
278    }
279
280    @Override
281    public List<ArtifactResult> resolveArtifacts(
282            RepositorySystemSession session, Collection<? extends ArtifactRequest> requests)
283            throws ArtifactResolutionException {
284        validateSession(session);
285        requireNonNull(requests, "requests cannot be null");
286
287        return artifactResolver.resolveArtifacts(session, requests);
288    }
289
290    @Override
291    public List<MetadataResult> resolveMetadata(
292            RepositorySystemSession session, Collection<? extends MetadataRequest> requests) {
293        validateSession(session);
294        requireNonNull(requests, "requests cannot be null");
295
296        return metadataResolver.resolveMetadata(session, requests);
297    }
298
299    @Override
300    public CollectResult collectDependencies(RepositorySystemSession session, CollectRequest request)
301            throws DependencyCollectionException {
302        validateSession(session);
303        requireNonNull(request, "request cannot be null");
304
305        return dependencyCollector.collectDependencies(session, request);
306    }
307
308    @Override
309    public DependencyResult resolveDependencies(RepositorySystemSession session, DependencyRequest request)
310            throws DependencyResolutionException {
311        validateSession(session);
312        requireNonNull(request, "request cannot be null");
313
314        RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
315
316        DependencyResult result = new DependencyResult(request);
317
318        DependencyCollectionException dce = null;
319        ArtifactResolutionException are = null;
320
321        if (request.getRoot() != null) {
322            result.setRoot(request.getRoot());
323        } else if (request.getCollectRequest() != null) {
324            CollectResult collectResult;
325            try {
326                request.getCollectRequest().setTrace(trace);
327                collectResult = dependencyCollector.collectDependencies(session, request.getCollectRequest());
328            } catch (DependencyCollectionException e) {
329                dce = e;
330                collectResult = e.getResult();
331            }
332            result.setRoot(collectResult.getRoot());
333            result.setCycles(collectResult.getCycles());
334            result.setCollectExceptions(collectResult.getExceptions());
335        } else {
336            throw new NullPointerException("dependency node and collect request cannot be null");
337        }
338
339        ArtifactRequestBuilder builder = new ArtifactRequestBuilder(trace);
340        DependencyFilter filter = request.getFilter();
341        DependencyVisitor visitor = (filter != null) ? new FilteringDependencyVisitor(builder, filter) : builder;
342        visitor = new TreeDependencyVisitor(visitor);
343
344        if (result.getRoot() != null) {
345            result.getRoot().accept(visitor);
346        }
347
348        List<ArtifactRequest> requests = builder.getRequests();
349
350        List<ArtifactResult> results;
351        try {
352            results = artifactResolver.resolveArtifacts(session, requests);
353        } catch (ArtifactResolutionException e) {
354            are = e;
355            results = e.getResults();
356        }
357        result.setArtifactResults(results);
358
359        updateNodesWithResolvedArtifacts(results);
360
361        if (dce != null) {
362            throw new DependencyResolutionException(result, dce);
363        } else if (are != null) {
364            throw new DependencyResolutionException(result, are);
365        }
366
367        return result;
368    }
369
370    private void updateNodesWithResolvedArtifacts(List<ArtifactResult> results) {
371        for (ArtifactResult result : results) {
372            Artifact artifact = result.getArtifact();
373            if (artifact != null) {
374                result.getRequest().getDependencyNode().setArtifact(artifact);
375            }
376        }
377    }
378
379    @Override
380    public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException {
381        validateSession(session);
382        requireNonNull(request, "request cannot be null");
383
384        return installer.install(session, request);
385    }
386
387    @Override
388    public DeployResult deploy(RepositorySystemSession session, DeployRequest request) throws DeploymentException {
389        validateSession(session);
390        requireNonNull(request, "request cannot be null");
391
392        return deployer.deploy(session, request);
393    }
394
395    @Override
396    public LocalRepositoryManager newLocalRepositoryManager(
397            RepositorySystemSession session, LocalRepository localRepository) {
398        requireNonNull(session, "session cannot be null");
399        requireNonNull(localRepository, "localRepository cannot be null");
400
401        try {
402            return localRepositoryProvider.newLocalRepositoryManager(session, localRepository);
403        } catch (NoLocalRepositoryManagerException e) {
404            throw new IllegalArgumentException(e.getMessage(), e);
405        }
406    }
407
408    @Override
409    public SyncContext newSyncContext(RepositorySystemSession session, boolean shared) {
410        validateSession(session);
411        return syncContextFactory.newInstance(session, shared);
412    }
413
414    @Override
415    public List<RemoteRepository> newResolutionRepositories(
416            RepositorySystemSession session, List<RemoteRepository> repositories) {
417        validateSession(session);
418        validateRepositories(repositories);
419
420        repositories = remoteRepositoryManager.aggregateRepositories(
421                session, new ArrayList<RemoteRepository>(), 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}