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.function.Supplier;
024
025import org.apache.maven.api.DependencyScope;
026import org.apache.maven.repository.internal.artifact.FatArtifactTraverser;
027import org.apache.maven.utils.Os;
028import org.eclipse.aether.RepositorySystem;
029import org.eclipse.aether.RepositorySystemSession;
030import org.eclipse.aether.RepositorySystemSession.CloseableSession;
031import org.eclipse.aether.RepositorySystemSession.SessionBuilder;
032import org.eclipse.aether.artifact.DefaultArtifactType;
033import org.eclipse.aether.collection.DependencyGraphTransformer;
034import org.eclipse.aether.collection.DependencyManager;
035import org.eclipse.aether.collection.DependencySelector;
036import org.eclipse.aether.collection.DependencyTraverser;
037import org.eclipse.aether.impl.scope.InternalScopeManager;
038import org.eclipse.aether.impl.scope.ScopeManagerConfiguration;
039import org.eclipse.aether.internal.impl.scope.ManagedDependencyContextRefiner;
040import org.eclipse.aether.internal.impl.scope.ManagedScopeDeriver;
041import org.eclipse.aether.internal.impl.scope.ManagedScopeSelector;
042import org.eclipse.aether.internal.impl.scope.OptionalDependencySelector;
043import org.eclipse.aether.internal.impl.scope.ScopeDependencySelector;
044import org.eclipse.aether.internal.impl.scope.ScopeManagerImpl;
045import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
046import org.eclipse.aether.util.artifact.DefaultArtifactTypeRegistry;
047import org.eclipse.aether.util.graph.manager.ClassicDependencyManager;
048import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager;
049import org.eclipse.aether.util.graph.selector.AndDependencySelector;
050import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
051import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
052import org.eclipse.aether.util.graph.transformer.ConfigurableVersionSelector;
053import org.eclipse.aether.util.graph.transformer.ConflictResolver;
054import org.eclipse.aether.util.graph.transformer.JavaDependencyContextRefiner;
055import org.eclipse.aether.util.graph.transformer.JavaScopeDeriver;
056import org.eclipse.aether.util.graph.transformer.JavaScopeSelector;
057import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector;
058import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy;
059
060import static java.util.Objects.requireNonNull;
061
062/**
063 * A simple {@link Supplier} of {@link SessionBuilder} instances, that on each call supplies newly
064 * constructed instance. To create session out of builder, use {@link SessionBuilder#build()}. For proper closing
065 * of sessions, use {@link CloseableSession#close()} method on built instance(s).
066 * <p>
067 * Extend this class and override methods to customize, if needed.
068 *
069 * @since 2.0.0
070 */
071public class SessionBuilderSupplier {
072    protected final RepositorySystem repositorySystem;
073    protected final InternalScopeManager scopeManager;
074
075    /**
076     * Creates Resolver 2 session using Maven 4 elements without {@link InternalScopeManager}.
077     */
078    public SessionBuilderSupplier(RepositorySystem repositorySystem) {
079        this(repositorySystem, null);
080    }
081
082    /**
083     * Creates Resolver 2 session using Maven 4 elements with or without {@link InternalScopeManager}.
084     */
085    public SessionBuilderSupplier(
086            RepositorySystem repositorySystem, ScopeManagerConfiguration scopeManagerConfiguration) {
087        this.repositorySystem = requireNonNull(repositorySystem);
088        this.scopeManager = scopeManagerConfiguration == null ? null : new ScopeManagerImpl(scopeManagerConfiguration);
089    }
090
091    public void configureSessionBuilder(RepositorySystemSession.SessionBuilder session) {
092        session.setSystemProperties(System.getProperties());
093        boolean caseSensitive = !Os.IS_WINDOWS;
094        System.getenv().forEach((key, value) -> {
095            key = "env." + (caseSensitive ? key : key.toUpperCase(Locale.ENGLISH));
096            session.setSystemProperty(key, value);
097        });
098        if (getScopeManager() != null) {
099            session.setScopeManager(getScopeManager());
100        }
101        session.setDependencyTraverser(getDependencyTraverser());
102        session.setDependencyManager(getDependencyManager());
103        session.setDependencySelector(getDependencySelector());
104        session.setDependencyGraphTransformer(getDependencyGraphTransformer());
105        session.setArtifactTypeRegistry(getArtifactTypeRegistry());
106        session.setArtifactDescriptorPolicy(getArtifactDescriptorPolicy());
107    }
108
109    public InternalScopeManager getScopeManager() {
110        return this.scopeManager;
111    }
112
113    public DependencyTraverser getDependencyTraverser() {
114        return new FatArtifactTraverser();
115    }
116
117    public DependencyManager getDependencyManager() {
118        return this.getDependencyManager(true);
119    }
120
121    public DependencyManager getDependencyManager(boolean transitive) {
122        if (getScopeManager() == null) {
123            return transitive ? new TransitiveDependencyManager() : new ClassicDependencyManager();
124        } else {
125            return transitive
126                    ? new TransitiveDependencyManager(getScopeManager())
127                    : new ClassicDependencyManager(getScopeManager());
128        }
129    }
130
131    public DependencySelector getDependencySelector() {
132        if (getScopeManager() == null) {
133            return new AndDependencySelector(
134                    ScopeDependencySelector.legacy(
135                            null, Arrays.asList(DependencyScope.TEST.id(), DependencyScope.PROVIDED.id())),
136                    OptionalDependencySelector.fromDirect(),
137                    new ExclusionDependencySelector());
138        } else {
139            return new AndDependencySelector(
140                    ScopeDependencySelector.legacy(
141                            null, Arrays.asList(DependencyScope.TEST.id(), DependencyScope.PROVIDED.id())),
142                    OptionalDependencySelector.fromDirect(),
143                    new ExclusionDependencySelector());
144        }
145    }
146
147    public DependencyGraphTransformer getDependencyGraphTransformer() {
148        if (getScopeManager() == null) {
149            return new ChainedDependencyGraphTransformer(
150                    new ConflictResolver(
151                            new ConfigurableVersionSelector(),
152                            new JavaScopeSelector(),
153                            new SimpleOptionalitySelector(),
154                            new JavaScopeDeriver()),
155                    new JavaDependencyContextRefiner());
156        } else {
157            return new ChainedDependencyGraphTransformer(
158                    new ConflictResolver(
159                            new ConfigurableVersionSelector(),
160                            new ManagedScopeSelector(getScopeManager()),
161                            new SimpleOptionalitySelector(),
162                            new ManagedScopeDeriver(getScopeManager())),
163                    new ManagedDependencyContextRefiner(getScopeManager()));
164        }
165    }
166
167    public DefaultArtifactTypeRegistry getArtifactTypeRegistry() {
168        DefaultArtifactTypeRegistry stereotypes = new DefaultArtifactTypeRegistry();
169        stereotypes.add(new DefaultArtifactType("pom"));
170        stereotypes.add(new DefaultArtifactType("maven-plugin", "jar", "", "java"));
171        stereotypes.add(new DefaultArtifactType("jar", "jar", "", "java"));
172        stereotypes.add(new DefaultArtifactType("ejb", "jar", "", "java"));
173        stereotypes.add(new DefaultArtifactType("ejb-client", "jar", "client", "java"));
174        stereotypes.add(new DefaultArtifactType("test-jar", "jar", "tests", "java"));
175        stereotypes.add(new DefaultArtifactType("javadoc", "jar", "javadoc", "java"));
176        stereotypes.add(new DefaultArtifactType("java-source", "jar", "sources", "java", false, false));
177        stereotypes.add(new DefaultArtifactType("fatjar", "jar", "", "java", true, true));
178        stereotypes.add(new DefaultArtifactType("war", "war", "", "java", false, true));
179        stereotypes.add(new DefaultArtifactType("ear", "ear", "", "java", false, true));
180        stereotypes.add(new DefaultArtifactType("rar", "rar", "", "java", false, true));
181        stereotypes.add(new DefaultArtifactType("par", "par", "", "java", false, true));
182        return stereotypes;
183    }
184
185    public ArtifactDescriptorPolicy getArtifactDescriptorPolicy() {
186        return new SimpleArtifactDescriptorPolicy(true, true);
187    }
188
189    /**
190     * Creates a new Maven-like repository system session by initializing the session with values typical for
191     * Maven-based resolution. In more detail, this method configures settings relevant for the processing of dependency
192     * graphs, most other settings remain at their generic default value. Use the various setters to further configure
193     * the session with authentication, mirror, proxy and other information required for your environment. At least,
194     * local repository manager needs to be configured to make session be able to create session instance.
195     *
196     * @return SessionBuilder configured with minimally required things for "Maven-based resolution". At least LRM must
197     * be set on builder to make it able to create session instances.
198     */
199    public RepositorySystemSession.SessionBuilder get() {
200        RepositorySystemSession.SessionBuilder builder = repositorySystem.createSessionBuilder();
201        configureSessionBuilder(builder);
202        return builder;
203    }
204}