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.supplier;
020
021import java.util.Arrays;
022import java.util.Locale;
023import java.util.Objects;
024import java.util.function.Supplier;
025
026import org.apache.maven.api.DependencyScope;
027import org.apache.maven.repository.internal.artifact.FatArtifactTraverser;
028import org.apache.maven.repository.internal.scopes.Maven4ScopeManagerConfiguration;
029import org.apache.maven.repository.internal.type.DefaultTypeProvider;
030import org.apache.maven.utils.Os;
031import org.eclipse.aether.RepositorySystem;
032import org.eclipse.aether.RepositorySystemSession;
033import org.eclipse.aether.RepositorySystemSession.CloseableSession;
034import org.eclipse.aether.RepositorySystemSession.SessionBuilder;
035import org.eclipse.aether.artifact.ArtifactTypeRegistry;
036import org.eclipse.aether.collection.DependencyGraphTransformer;
037import org.eclipse.aether.collection.DependencyManager;
038import org.eclipse.aether.collection.DependencySelector;
039import org.eclipse.aether.collection.DependencyTraverser;
040import org.eclipse.aether.impl.scope.InternalScopeManager;
041import org.eclipse.aether.internal.impl.scope.ManagedDependencyContextRefiner;
042import org.eclipse.aether.internal.impl.scope.ManagedScopeDeriver;
043import org.eclipse.aether.internal.impl.scope.ManagedScopeSelector;
044import org.eclipse.aether.internal.impl.scope.OptionalDependencySelector;
045import org.eclipse.aether.internal.impl.scope.ScopeDependencySelector;
046import org.eclipse.aether.internal.impl.scope.ScopeManagerImpl;
047import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
048import org.eclipse.aether.util.artifact.DefaultArtifactTypeRegistry;
049import org.eclipse.aether.util.graph.manager.ClassicDependencyManager;
050import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager;
051import org.eclipse.aether.util.graph.selector.AndDependencySelector;
052import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
053import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
054import org.eclipse.aether.util.graph.transformer.ConfigurableVersionSelector;
055import org.eclipse.aether.util.graph.transformer.ConflictResolver;
056import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector;
057import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy;
058
059/**
060 * A simple {@link Supplier} of {@link SessionBuilder} instances, that on each call supplies newly
061 * constructed instance. To create session out of builder, use {@link SessionBuilder#build()}. For proper closing
062 * of sessions, use {@link CloseableSession#close()} method on built instance(s).
063 * <p>
064 * Extend this class and override methods to customize, if needed.
065 *
066 * @since 2.0.0
067 */
068public class SessionBuilderSupplier {
069    protected final RepositorySystem repositorySystem;
070    protected final InternalScopeManager scopeManager;
071
072    public SessionBuilderSupplier(RepositorySystem repositorySystem) {
073        this.repositorySystem = Objects.requireNonNull(repositorySystem);
074        this.scopeManager = new ScopeManagerImpl(Maven4ScopeManagerConfiguration.INSTANCE);
075    }
076
077    /** @deprecated */
078    @Deprecated
079    public SessionBuilderSupplier() {
080        this.repositorySystem = null;
081        this.scopeManager = new ScopeManagerImpl(Maven4ScopeManagerConfiguration.INSTANCE);
082    }
083
084    protected InternalScopeManager getScopeManager() {
085        return this.scopeManager;
086    }
087
088    protected DependencyTraverser getDependencyTraverser() {
089        return new FatArtifactTraverser();
090    }
091
092    protected DependencyManager getDependencyManager() {
093        return this.getDependencyManager(true);
094    }
095
096    public DependencyManager getDependencyManager(boolean transitive) {
097        return transitive
098                ? new TransitiveDependencyManager(this.getScopeManager())
099                : new ClassicDependencyManager(this.scopeManager);
100    }
101
102    protected DependencySelector getDependencySelector() {
103        return new AndDependencySelector(new DependencySelector[] {
104            ScopeDependencySelector.legacy(
105                    null, Arrays.asList(DependencyScope.TEST.id(), DependencyScope.PROVIDED.id())),
106            OptionalDependencySelector.fromDirect(),
107            new ExclusionDependencySelector()
108        });
109    }
110
111    protected DependencyGraphTransformer getDependencyGraphTransformer() {
112        return new ChainedDependencyGraphTransformer(
113                new ConflictResolver(
114                        new ConfigurableVersionSelector(),
115                        new ManagedScopeSelector(this.getScopeManager()),
116                        new SimpleOptionalitySelector(),
117                        new ManagedScopeDeriver(this.getScopeManager())),
118                new ManagedDependencyContextRefiner(this.getScopeManager()));
119    }
120
121    protected ArtifactTypeRegistry getArtifactTypeRegistry() {
122        DefaultArtifactTypeRegistry stereotypes = new DefaultArtifactTypeRegistry();
123        new DefaultTypeProvider().types().forEach(stereotypes::add);
124        return stereotypes;
125    }
126
127    protected ArtifactDescriptorPolicy getArtifactDescriptorPolicy() {
128        return new SimpleArtifactDescriptorPolicy(true, true);
129    }
130
131    protected void configureSessionBuilder(RepositorySystemSession.SessionBuilder session) {
132        session.setDependencyTraverser(this.getDependencyTraverser());
133        session.setDependencyManager(this.getDependencyManager());
134        session.setDependencySelector(this.getDependencySelector());
135        session.setDependencyGraphTransformer(this.getDependencyGraphTransformer());
136        session.setArtifactTypeRegistry(this.getArtifactTypeRegistry());
137        session.setArtifactDescriptorPolicy(this.getArtifactDescriptorPolicy());
138        session.setScopeManager(this.getScopeManager());
139
140        session.setSystemProperties(System.getProperties());
141        boolean caseSensitive = !Os.IS_WINDOWS;
142        System.getenv().forEach((key, value) -> {
143            key = "env." + (caseSensitive ? key : key.toUpperCase(Locale.ENGLISH));
144            session.setSystemProperty(key, value);
145        });
146    }
147
148    public RepositorySystemSession.SessionBuilder get() {
149        Objects.requireNonNull(this.repositorySystem, "repositorySystem");
150        RepositorySystemSession.SessionBuilder builder = this.repositorySystem.createSessionBuilder();
151        this.configureSessionBuilder(builder);
152        return builder;
153    }
154}