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