View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether;
20  
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.function.Function;
25  
26  import org.eclipse.aether.artifact.ArtifactType;
27  import org.eclipse.aether.artifact.ArtifactTypeRegistry;
28  import org.eclipse.aether.collection.DependencyCollectionChecker;
29  import org.eclipse.aether.collection.DependencyGraphTransformer;
30  import org.eclipse.aether.collection.DependencyManager;
31  import org.eclipse.aether.collection.DependencySelector;
32  import org.eclipse.aether.collection.DependencyTraverser;
33  import org.eclipse.aether.collection.VersionFilter;
34  import org.eclipse.aether.repository.Authentication;
35  import org.eclipse.aether.repository.AuthenticationSelector;
36  import org.eclipse.aether.repository.LocalRepository;
37  import org.eclipse.aether.repository.LocalRepositoryManager;
38  import org.eclipse.aether.repository.MirrorSelector;
39  import org.eclipse.aether.repository.Proxy;
40  import org.eclipse.aether.repository.ProxySelector;
41  import org.eclipse.aether.repository.RemoteRepository;
42  import org.eclipse.aether.repository.RepositoryPolicy;
43  import org.eclipse.aether.repository.WorkspaceReader;
44  import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
45  import org.eclipse.aether.resolution.ResolutionErrorPolicy;
46  import org.eclipse.aether.scope.ScopeManager;
47  import org.eclipse.aether.scope.SystemDependencyScope;
48  import org.eclipse.aether.transfer.TransferListener;
49  
50  import static java.util.Objects.requireNonNull;
51  
52  /**
53   * A legacy repository system session. It is usable to "derive" sessions from existing session instances (using
54   * copy-constructor), but the recommended way to derive sessions is using
55   * {@link org.eclipse.aether.RepositorySystemSession.SessionBuilder#withRepositorySystemSession(RepositorySystemSession)}
56   * instead.
57   * <p>
58   * <em>Important: while the default constructor on this class is deprecated only, it is left only to guarantee
59   * backward compatibility with legacy code, but the default constructor should not be used anymore. Using that
60   * constructor will lead to resource leaks.</em>
61   * <p>
62   * <strong>Note:</strong> This class is not thread-safe. It is assumed that the mutators get only called during an
63   * initialization phase and that the session itself is not changed once initialized and being used by the repository
64   * system. It is recommended to call {@link #setReadOnly()} once the session has been fully initialized to prevent
65   * accidental manipulation of it afterward.
66   *
67   * @see RepositorySystem#createSessionBuilder()
68   * @see RepositorySystemSession.SessionBuilder
69   * @see RepositorySystemSession.CloseableSession
70   */
71  public final class DefaultRepositorySystemSession implements RepositorySystemSession {
72      private boolean readOnly;
73  
74      private boolean offline;
75  
76      private boolean ignoreArtifactDescriptorRepositories;
77  
78      private ResolutionErrorPolicy resolutionErrorPolicy;
79  
80      private ArtifactDescriptorPolicy artifactDescriptorPolicy;
81  
82      private String checksumPolicy;
83  
84      private String artifactUpdatePolicy;
85  
86      private String metadataUpdatePolicy;
87  
88      private LocalRepositoryManager localRepositoryManager;
89  
90      private WorkspaceReader workspaceReader;
91  
92      private RepositoryListener repositoryListener;
93  
94      private TransferListener transferListener;
95  
96      private Map<String, String> systemProperties;
97  
98      private Map<String, String> systemPropertiesView;
99  
100     private Map<String, String> userProperties;
101 
102     private Map<String, String> userPropertiesView;
103 
104     private Map<String, Object> configProperties;
105 
106     private Map<String, Object> configPropertiesView;
107 
108     private MirrorSelector mirrorSelector;
109 
110     private ProxySelector proxySelector;
111 
112     private AuthenticationSelector authenticationSelector;
113 
114     private ArtifactTypeRegistry artifactTypeRegistry;
115 
116     private DependencyTraverser dependencyTraverser;
117 
118     private DependencyManager dependencyManager;
119 
120     private DependencySelector dependencySelector;
121 
122     private VersionFilter versionFilter;
123 
124     private DependencyGraphTransformer dependencyGraphTransformer;
125 
126     private SessionData data;
127 
128     private RepositoryCache cache;
129 
130     private ScopeManager scopeManager;
131 
132     private DependencyCollectionChecker dependencyCollectionChecker;
133 
134     private final Function<Runnable, Boolean> onSessionEndedRegistrar;
135 
136     /**
137      * Creates an uninitialized session. <em>Note:</em> The new session is not ready to use, as a bare minimum,
138      * {@link #setLocalRepositoryManager(LocalRepositoryManager)} needs to be called but usually other settings also
139      * need to be customized to achieve meaningful behavior.
140      *
141      * @deprecated This way of creating session should be avoided, is in place just to offer backward binary
142      * compatibility with Resolver 1.x using code, but offers reduced functionality.
143      * Use {@link RepositorySystem#createSessionBuilder()} instead.
144      */
145     @Deprecated
146     public DefaultRepositorySystemSession() {
147         this(h -> false);
148     }
149 
150     /**
151      * Creates an uninitialized session. <em>Note:</em> The new session is not ready to use, as a bare minimum,
152      * {@link #setLocalRepositoryManager(LocalRepositoryManager)} needs to be called but usually other settings also
153      * need to be customized to achieve meaningful behavior.
154      * <p>
155      * Note: preferred way to create sessions is {@link RepositorySystem#createSessionBuilder()}, as then client code
156      * does not have to fiddle with session close callbacks. This constructor is meant more for testing purposes.
157      *
158      * @param onSessionEndedRegistrar The function to register an "on session ended" handler with, invoked with the
159      *            handler and returning {@code true} if registration succeeded, must not be {@code null}.
160      * @since 2.0.0
161      */
162     public DefaultRepositorySystemSession(Function<Runnable, Boolean> onSessionEndedRegistrar) {
163         systemProperties = new HashMap<>();
164         systemPropertiesView = Collections.unmodifiableMap(systemProperties);
165         userProperties = new HashMap<>();
166         userPropertiesView = Collections.unmodifiableMap(userProperties);
167         configProperties = new HashMap<>();
168         configPropertiesView = Collections.unmodifiableMap(configProperties);
169         mirrorSelector = NullMirrorSelector.INSTANCE;
170         proxySelector = PassthroughProxySelector.INSTANCE;
171         authenticationSelector = PassthroughAuthenticationSelector.INSTANCE;
172         artifactTypeRegistry = NullArtifactTypeRegistry.INSTANCE;
173         data = new DefaultSessionData();
174         this.onSessionEndedRegistrar = requireNonNull(onSessionEndedRegistrar, "onSessionEndedRegistrar");
175     }
176 
177     /**
178      * Creates a shallow copy of the specified session. Actually, the copy is not completely shallow, all maps holding
179      * system/user/config properties are copied as well. In other words, invoking any mutator on the new session itself
180      * has no effect on the original session. Other mutable objects like the session data and cache (if any) are not
181      * copied and will be shared with the original session unless reconfigured.
182      *
183      * @param session The session to copy, must not be {@code null}.
184      */
185     public DefaultRepositorySystemSession(RepositorySystemSession session) {
186         requireNonNull(session, "repository system session cannot be null");
187 
188         setOffline(session.isOffline());
189         setIgnoreArtifactDescriptorRepositories(session.isIgnoreArtifactDescriptorRepositories());
190         setResolutionErrorPolicy(session.getResolutionErrorPolicy());
191         setArtifactDescriptorPolicy(session.getArtifactDescriptorPolicy());
192         setChecksumPolicy(session.getChecksumPolicy());
193         setUpdatePolicy(session.getUpdatePolicy());
194         setMetadataUpdatePolicy(session.getMetadataUpdatePolicy());
195         setLocalRepositoryManager(session.getLocalRepositoryManager());
196         setWorkspaceReader(session.getWorkspaceReader());
197         setRepositoryListener(session.getRepositoryListener());
198         setTransferListener(session.getTransferListener());
199         setSystemProperties(session.getSystemProperties());
200         setUserProperties(session.getUserProperties());
201         setConfigProperties(session.getConfigProperties());
202         setMirrorSelector(session.getMirrorSelector());
203         setProxySelector(session.getProxySelector());
204         setAuthenticationSelector(session.getAuthenticationSelector());
205         setArtifactTypeRegistry(session.getArtifactTypeRegistry());
206         setDependencyTraverser(session.getDependencyTraverser());
207         setDependencyManager(session.getDependencyManager());
208         setDependencySelector(session.getDependencySelector());
209         setVersionFilter(session.getVersionFilter());
210         setDependencyGraphTransformer(session.getDependencyGraphTransformer());
211         setData(session.getData());
212         setCache(session.getCache());
213         setScopeManager(session.getScopeManager());
214         setDependencyCollectionChecker(session.getDependencyCollectionChecker());
215         this.onSessionEndedRegistrar = session::addOnSessionEndedHandler;
216     }
217 
218     @Override
219     public boolean isOffline() {
220         return offline;
221     }
222 
223     /**
224      * Controls whether the repository system operates in offline mode and avoids/refuses any access to remote
225      * repositories.
226      *
227      * @param offline {@code true} if the repository system is in offline mode, {@code false} otherwise.
228      * @return This session for chaining, never {@code null}.
229      */
230     public DefaultRepositorySystemSession setOffline(boolean offline) {
231         verifyStateForMutation();
232         this.offline = offline;
233         return this;
234     }
235 
236     @Override
237     public boolean isIgnoreArtifactDescriptorRepositories() {
238         return ignoreArtifactDescriptorRepositories;
239     }
240 
241     /**
242      * Controls whether repositories declared in artifact descriptors should be ignored during transitive dependency
243      * collection. If enabled, only the repositories originally provided with the collect request will be considered.
244      *
245      * @param ignoreArtifactDescriptorRepositories {@code true} to ignore additional repositories from artifact
246      *                                             descriptors, {@code false} to merge those with the originally
247      *                                             specified repositories.
248      * @return This session for chaining, never {@code null}.
249      */
250     public DefaultRepositorySystemSession setIgnoreArtifactDescriptorRepositories(
251             boolean ignoreArtifactDescriptorRepositories) {
252         verifyStateForMutation();
253         this.ignoreArtifactDescriptorRepositories = ignoreArtifactDescriptorRepositories;
254         return this;
255     }
256 
257     @Override
258     public ResolutionErrorPolicy getResolutionErrorPolicy() {
259         return resolutionErrorPolicy;
260     }
261 
262     /**
263      * Sets the policy which controls whether resolutions errors from remote repositories should be cached.
264      *
265      * @param resolutionErrorPolicy The resolution error policy for this session, may be {@code null} if resolution
266      *                              errors should generally not be cached.
267      * @return This session for chaining, never {@code null}.
268      */
269     public DefaultRepositorySystemSession setResolutionErrorPolicy(ResolutionErrorPolicy resolutionErrorPolicy) {
270         verifyStateForMutation();
271         this.resolutionErrorPolicy = resolutionErrorPolicy;
272         return this;
273     }
274 
275     @Override
276     public ArtifactDescriptorPolicy getArtifactDescriptorPolicy() {
277         return artifactDescriptorPolicy;
278     }
279 
280     /**
281      * Sets the policy which controls how errors related to reading artifact descriptors should be handled.
282      *
283      * @param artifactDescriptorPolicy The descriptor error policy for this session, may be {@code null} if descriptor
284      *                                 errors should generally not be tolerated.
285      * @return This session for chaining, never {@code null}.
286      */
287     public DefaultRepositorySystemSession setArtifactDescriptorPolicy(
288             ArtifactDescriptorPolicy artifactDescriptorPolicy) {
289         verifyStateForMutation();
290         this.artifactDescriptorPolicy = artifactDescriptorPolicy;
291         return this;
292     }
293 
294     @Override
295     public String getChecksumPolicy() {
296         return checksumPolicy;
297     }
298 
299     /**
300      * Sets the global checksum policy. If set, the global checksum policy overrides the checksum policies of the remote
301      * repositories being used for resolution.
302      *
303      * @param checksumPolicy The global checksum policy, may be {@code null}/empty to apply the per-repository policies.
304      * @return This session for chaining, never {@code null}.
305      * @see RepositoryPolicy#CHECKSUM_POLICY_FAIL
306      * @see RepositoryPolicy#CHECKSUM_POLICY_IGNORE
307      * @see RepositoryPolicy#CHECKSUM_POLICY_WARN
308      */
309     public DefaultRepositorySystemSession setChecksumPolicy(String checksumPolicy) {
310         verifyStateForMutation();
311         this.checksumPolicy = checksumPolicy;
312         return this;
313     }
314 
315     @Override
316     public String getUpdatePolicy() {
317         return getArtifactUpdatePolicy();
318     }
319 
320     /**
321      * Sets the global update policy. If set, the global update policy overrides the update policies of the remote
322      * repositories being used for resolution.
323      * <p>
324      * This method is meant for code that does not want to distinguish between artifact and metadata policies.
325      * Note: applications should either use get/set updatePolicy (this method and
326      * {@link RepositorySystemSession#getUpdatePolicy()}) or also distinguish between artifact and
327      * metadata update policies (and use other methods), but <em>should not mix the two!</em>
328      *
329      * @param updatePolicy The global update policy, may be {@code null}/empty to apply the per-repository policies.
330      * @return This session for chaining, never {@code null}.
331      * @see RepositoryPolicy#UPDATE_POLICY_ALWAYS
332      * @see RepositoryPolicy#UPDATE_POLICY_DAILY
333      * @see RepositoryPolicy#UPDATE_POLICY_NEVER
334      * @see #setArtifactUpdatePolicy(String)
335      * @see #setMetadataUpdatePolicy(String)
336      */
337     public DefaultRepositorySystemSession setUpdatePolicy(String updatePolicy) {
338         verifyStateForMutation();
339         setArtifactUpdatePolicy(updatePolicy);
340         setMetadataUpdatePolicy(updatePolicy);
341         return this;
342     }
343 
344     @Override
345     public String getArtifactUpdatePolicy() {
346         return artifactUpdatePolicy;
347     }
348 
349     /**
350      * Sets the global artifact update policy. If set, the global update policy overrides the artifact update policies
351      * of the remote repositories being used for resolution.
352      *
353      * @param artifactUpdatePolicy The global update policy, may be {@code null}/empty to apply the per-repository policies.
354      * @return This session for chaining, never {@code null}.
355      * @see RepositoryPolicy#UPDATE_POLICY_ALWAYS
356      * @see RepositoryPolicy#UPDATE_POLICY_DAILY
357      * @see RepositoryPolicy#UPDATE_POLICY_NEVER
358      * @since 2.0.0
359      */
360     public DefaultRepositorySystemSession setArtifactUpdatePolicy(String artifactUpdatePolicy) {
361         verifyStateForMutation();
362         this.artifactUpdatePolicy = artifactUpdatePolicy;
363         return this;
364     }
365 
366     @Override
367     public String getMetadataUpdatePolicy() {
368         return metadataUpdatePolicy;
369     }
370 
371     /**
372      * Sets the global metadata update policy. If set, the global update policy overrides the metadata update policies
373      * of the remote repositories being used for resolution.
374      *
375      * @param metadataUpdatePolicy The global update policy, may be {@code null}/empty to apply the per-repository policies.
376      * @return This session for chaining, never {@code null}.
377      * @see RepositoryPolicy#UPDATE_POLICY_ALWAYS
378      * @see RepositoryPolicy#UPDATE_POLICY_DAILY
379      * @see RepositoryPolicy#UPDATE_POLICY_NEVER
380      * @since 2.0.0
381      */
382     public DefaultRepositorySystemSession setMetadataUpdatePolicy(String metadataUpdatePolicy) {
383         verifyStateForMutation();
384         this.metadataUpdatePolicy = metadataUpdatePolicy;
385         return this;
386     }
387 
388     @Override
389     public LocalRepository getLocalRepository() {
390         LocalRepositoryManager lrm = getLocalRepositoryManager();
391         return (lrm != null) ? lrm.getRepository() : null;
392     }
393 
394     @Override
395     public LocalRepositoryManager getLocalRepositoryManager() {
396         return localRepositoryManager;
397     }
398 
399     /**
400      * Sets the local repository manager used during this session. <em>Note:</em> Eventually, a valid session must have
401      * a local repository manager set.
402      *
403      * @param localRepositoryManager The local repository manager used during this session, may be {@code null}.
404      * @return This session for chaining, never {@code null}.
405      */
406     public DefaultRepositorySystemSession setLocalRepositoryManager(LocalRepositoryManager localRepositoryManager) {
407         verifyStateForMutation();
408         this.localRepositoryManager = localRepositoryManager;
409         return this;
410     }
411 
412     @Override
413     public WorkspaceReader getWorkspaceReader() {
414         return workspaceReader;
415     }
416 
417     /**
418      * Sets the workspace reader used during this session. If set, the workspace reader will usually be consulted first
419      * to resolve artifacts.
420      *
421      * @param workspaceReader The workspace reader for this session, may be {@code null} if none.
422      * @return This session for chaining, never {@code null}.
423      */
424     public DefaultRepositorySystemSession setWorkspaceReader(WorkspaceReader workspaceReader) {
425         verifyStateForMutation();
426         this.workspaceReader = workspaceReader;
427         return this;
428     }
429 
430     @Override
431     public RepositoryListener getRepositoryListener() {
432         return repositoryListener;
433     }
434 
435     /**
436      * Sets the listener being notified of actions in the repository system.
437      *
438      * @param repositoryListener The repository listener, may be {@code null} if none.
439      * @return This session for chaining, never {@code null}.
440      */
441     public DefaultRepositorySystemSession setRepositoryListener(RepositoryListener repositoryListener) {
442         verifyStateForMutation();
443         this.repositoryListener = repositoryListener;
444         return this;
445     }
446 
447     @Override
448     public TransferListener getTransferListener() {
449         return transferListener;
450     }
451 
452     /**
453      * Sets the listener being notified of uploads/downloads by the repository system.
454      *
455      * @param transferListener The transfer listener, may be {@code null} if none.
456      * @return This session for chaining, never {@code null}.
457      */
458     public DefaultRepositorySystemSession setTransferListener(TransferListener transferListener) {
459         verifyStateForMutation();
460         this.transferListener = transferListener;
461         return this;
462     }
463 
464     private <T> Map<String, T> copySafe(Map<?, ?> table, Class<T> valueType) {
465         Map<String, T> map;
466         if (table == null || table.isEmpty()) {
467             map = new HashMap<>();
468         } else {
469             map = new HashMap<>((int) (table.size() / 0.75f) + 1);
470             for (Map.Entry<?, ?> entry : table.entrySet()) {
471                 Object key = entry.getKey();
472                 if (key instanceof String) {
473                     Object value = entry.getValue();
474                     if (valueType.isInstance(value)) {
475                         map.put(key.toString(), valueType.cast(value));
476                     }
477                 }
478             }
479         }
480         return map;
481     }
482 
483     @Override
484     public Map<String, String> getSystemProperties() {
485         return systemPropertiesView;
486     }
487 
488     /**
489      * Sets the system properties to use, e.g. for processing of artifact descriptors. System properties are usually
490      * collected from the runtime environment like {@link System#getProperties()} and environment variables.
491      * <p>
492      * <em>Note:</em> System properties are of type {@code Map<String, String>} and any key-value pair in the input map
493      * that doesn't match this type will be silently ignored.
494      *
495      * @param systemProperties The system properties, may be {@code null} or empty if none.
496      * @return This session for chaining, never {@code null}.
497      */
498     public DefaultRepositorySystemSession setSystemProperties(Map<?, ?> systemProperties) {
499         verifyStateForMutation();
500         this.systemProperties = copySafe(systemProperties, String.class);
501         systemPropertiesView = Collections.unmodifiableMap(this.systemProperties);
502         return this;
503     }
504 
505     /**
506      * Sets the specified system property.
507      *
508      * @param key   The property key, must not be {@code null}.
509      * @param value The property value, may be {@code null} to remove/unset the property.
510      * @return This session for chaining, never {@code null}.
511      */
512     public DefaultRepositorySystemSession setSystemProperty(String key, String value) {
513         verifyStateForMutation();
514         if (value != null) {
515             systemProperties.put(key, value);
516         } else {
517             systemProperties.remove(key);
518         }
519         return this;
520     }
521 
522     @Override
523     public Map<String, String> getUserProperties() {
524         return userPropertiesView;
525     }
526 
527     /**
528      * Sets the user properties to use, e.g. for processing of artifact descriptors. User properties are similar to
529      * system properties but are set on the discretion of the user and hence are considered of higher priority than
530      * system properties in case of conflicts.
531      * <p>
532      * <em>Note:</em> User properties are of type {@code Map<String, String>} and any key-value pair in the input map
533      * that doesn't match this type will be silently ignored.
534      *
535      * @param userProperties The user properties, may be {@code null} or empty if none.
536      * @return This session for chaining, never {@code null}.
537      */
538     public DefaultRepositorySystemSession setUserProperties(Map<?, ?> userProperties) {
539         verifyStateForMutation();
540         this.userProperties = copySafe(userProperties, String.class);
541         userPropertiesView = Collections.unmodifiableMap(this.userProperties);
542         return this;
543     }
544 
545     /**
546      * Sets the specified user property.
547      *
548      * @param key   The property key, must not be {@code null}.
549      * @param value The property value, may be {@code null} to remove/unset the property.
550      * @return This session for chaining, never {@code null}.
551      */
552     public DefaultRepositorySystemSession setUserProperty(String key, String value) {
553         verifyStateForMutation();
554         if (value != null) {
555             userProperties.put(key, value);
556         } else {
557             userProperties.remove(key);
558         }
559         return this;
560     }
561 
562     @Override
563     public Map<String, Object> getConfigProperties() {
564         return configPropertiesView;
565     }
566 
567     /**
568      * Sets the configuration properties used to tweak internal aspects of the repository system (e.g. thread pooling,
569      * connector-specific behavior, etc.).
570      * <p>
571      * <em>Note:</em> Configuration properties are of type {@code Map<String, Object>} and any key-value pair in the
572      * input map that doesn't match this type will be silently ignored.
573      *
574      * @param configProperties The configuration properties, may be {@code null} or empty if none.
575      * @return This session for chaining, never {@code null}.
576      */
577     public DefaultRepositorySystemSession setConfigProperties(Map<?, ?> configProperties) {
578         verifyStateForMutation();
579         this.configProperties = copySafe(configProperties, Object.class);
580         configPropertiesView = Collections.unmodifiableMap(this.configProperties);
581         return this;
582     }
583 
584     /**
585      * Sets the specified configuration property.
586      *
587      * @param key   The property key, must not be {@code null}.
588      * @param value The property value, may be {@code null} to remove/unset the property.
589      * @return This session for chaining, never {@code null}.
590      */
591     public DefaultRepositorySystemSession setConfigProperty(String key, Object value) {
592         verifyStateForMutation();
593         if (value != null) {
594             configProperties.put(key, value);
595         } else {
596             configProperties.remove(key);
597         }
598         return this;
599     }
600 
601     @Override
602     public MirrorSelector getMirrorSelector() {
603         return mirrorSelector;
604     }
605 
606     /**
607      * Sets the mirror selector to use for repositories discovered in artifact descriptors. Note that this selector is
608      * not used for remote repositories which are passed as request parameters to the repository system, those
609      * repositories are supposed to denote the effective repositories.
610      *
611      * @param mirrorSelector The mirror selector to use, may be {@code null}.
612      * @return This session for chaining, never {@code null}.
613      */
614     public DefaultRepositorySystemSession setMirrorSelector(MirrorSelector mirrorSelector) {
615         verifyStateForMutation();
616         this.mirrorSelector = mirrorSelector;
617         if (this.mirrorSelector == null) {
618             this.mirrorSelector = NullMirrorSelector.INSTANCE;
619         }
620         return this;
621     }
622 
623     @Override
624     public ProxySelector getProxySelector() {
625         return proxySelector;
626     }
627 
628     /**
629      * Sets the proxy selector to use for repositories discovered in artifact descriptors. Note that this selector is
630      * not used for remote repositories which are passed as request parameters to the repository system, those
631      * repositories are supposed to have their proxy (if any) already set.
632      *
633      * @param proxySelector The proxy selector to use, may be {@code null}.
634      * @return This session for chaining, never {@code null}.
635      * @see org.eclipse.aether.repository.RemoteRepository#getProxy()
636      */
637     public DefaultRepositorySystemSession setProxySelector(ProxySelector proxySelector) {
638         verifyStateForMutation();
639         this.proxySelector = proxySelector;
640         if (this.proxySelector == null) {
641             this.proxySelector = PassthroughProxySelector.INSTANCE;
642         }
643         return this;
644     }
645 
646     @Override
647     public AuthenticationSelector getAuthenticationSelector() {
648         return authenticationSelector;
649     }
650 
651     /**
652      * Sets the authentication selector to use for repositories discovered in artifact descriptors. Note that this
653      * selector is not used for remote repositories which are passed as request parameters to the repository system,
654      * those repositories are supposed to have their authentication (if any) already set.
655      *
656      * @param authenticationSelector The authentication selector to use, may be {@code null}.
657      * @return This session for chaining, never {@code null}.
658      * @see org.eclipse.aether.repository.RemoteRepository#getAuthentication()
659      */
660     public DefaultRepositorySystemSession setAuthenticationSelector(AuthenticationSelector authenticationSelector) {
661         verifyStateForMutation();
662         this.authenticationSelector = authenticationSelector;
663         if (this.authenticationSelector == null) {
664             this.authenticationSelector = PassthroughAuthenticationSelector.INSTANCE;
665         }
666         return this;
667     }
668 
669     @Override
670     public ArtifactTypeRegistry getArtifactTypeRegistry() {
671         return artifactTypeRegistry;
672     }
673 
674     /**
675      * Sets the registry of artifact types recognized by this session.
676      *
677      * @param artifactTypeRegistry The artifact type registry, may be {@code null}.
678      * @return This session for chaining, never {@code null}.
679      */
680     public DefaultRepositorySystemSession setArtifactTypeRegistry(ArtifactTypeRegistry artifactTypeRegistry) {
681         verifyStateForMutation();
682         this.artifactTypeRegistry = artifactTypeRegistry;
683         if (this.artifactTypeRegistry == null) {
684             this.artifactTypeRegistry = NullArtifactTypeRegistry.INSTANCE;
685         }
686         return this;
687     }
688 
689     @Override
690     public DependencyTraverser getDependencyTraverser() {
691         return dependencyTraverser;
692     }
693 
694     /**
695      * Sets the dependency traverser to use for building dependency graphs.
696      *
697      * @param dependencyTraverser The dependency traverser to use for building dependency graphs, may be {@code null}.
698      * @return This session for chaining, never {@code null}.
699      */
700     public DefaultRepositorySystemSession setDependencyTraverser(DependencyTraverser dependencyTraverser) {
701         verifyStateForMutation();
702         this.dependencyTraverser = dependencyTraverser;
703         return this;
704     }
705 
706     @Override
707     public DependencyManager getDependencyManager() {
708         return dependencyManager;
709     }
710 
711     /**
712      * Sets the dependency manager to use for building dependency graphs.
713      *
714      * @param dependencyManager The dependency manager to use for building dependency graphs, may be {@code null}.
715      * @return This session for chaining, never {@code null}.
716      */
717     public DefaultRepositorySystemSession setDependencyManager(DependencyManager dependencyManager) {
718         verifyStateForMutation();
719         this.dependencyManager = dependencyManager;
720         return this;
721     }
722 
723     @Override
724     public DependencySelector getDependencySelector() {
725         return dependencySelector;
726     }
727 
728     /**
729      * Sets the dependency selector to use for building dependency graphs.
730      *
731      * @param dependencySelector The dependency selector to use for building dependency graphs, may be {@code null}.
732      * @return This session for chaining, never {@code null}.
733      */
734     public DefaultRepositorySystemSession setDependencySelector(DependencySelector dependencySelector) {
735         verifyStateForMutation();
736         this.dependencySelector = dependencySelector;
737         return this;
738     }
739 
740     @Override
741     public VersionFilter getVersionFilter() {
742         return versionFilter;
743     }
744 
745     /**
746      * Sets the version filter to use for building dependency graphs.
747      *
748      * @param versionFilter The version filter to use for building dependency graphs, may be {@code null} to not filter
749      *                      versions.
750      * @return This session for chaining, never {@code null}.
751      */
752     public DefaultRepositorySystemSession setVersionFilter(VersionFilter versionFilter) {
753         verifyStateForMutation();
754         this.versionFilter = versionFilter;
755         return this;
756     }
757 
758     @Override
759     public DependencyGraphTransformer getDependencyGraphTransformer() {
760         return dependencyGraphTransformer;
761     }
762 
763     /**
764      * Sets the dependency graph transformer to use for building dependency graphs.
765      *
766      * @param dependencyGraphTransformer The dependency graph transformer to use for building dependency graphs, may be
767      *                                   {@code null}.
768      * @return This session for chaining, never {@code null}.
769      */
770     public DefaultRepositorySystemSession setDependencyGraphTransformer(
771             DependencyGraphTransformer dependencyGraphTransformer) {
772         verifyStateForMutation();
773         this.dependencyGraphTransformer = dependencyGraphTransformer;
774         return this;
775     }
776 
777     @Override
778     public SessionData getData() {
779         return data;
780     }
781 
782     /**
783      * Sets the custom data associated with this session.
784      *
785      * @param data The session data, may be {@code null}.
786      * @return This session for chaining, never {@code null}.
787      */
788     public DefaultRepositorySystemSession setData(SessionData data) {
789         verifyStateForMutation();
790         this.data = data;
791         if (this.data == null) {
792             this.data = new DefaultSessionData();
793         }
794         return this;
795     }
796 
797     @Override
798     public RepositoryCache getCache() {
799         return cache;
800     }
801 
802     /**
803      * Sets the cache the repository system may use to save data for future reuse during the session.
804      *
805      * @param cache The repository cache, may be {@code null} if none.
806      * @return This session for chaining, never {@code null}.
807      */
808     public DefaultRepositorySystemSession setCache(RepositoryCache cache) {
809         verifyStateForMutation();
810         this.cache = cache;
811         return this;
812     }
813 
814     @Override
815     public ScopeManager getScopeManager() {
816         return scopeManager;
817     }
818 
819     /**
820      * Sets the scope manager, may be {@code null}.
821      *
822      * @param scopeManager The scope manager, may be {@code null}.
823      * @return The session for chaining, never {@code null}.
824      * @since 2.0.0
825      */
826     public DefaultRepositorySystemSession setScopeManager(ScopeManager scopeManager) {
827         verifyStateForMutation();
828         this.scopeManager = scopeManager;
829         return this;
830     }
831 
832     @Override
833     public SystemDependencyScope getSystemDependencyScope() {
834         if (scopeManager != null) {
835             return scopeManager.getSystemDependencyScope().orElse(null);
836         } else {
837             return SystemDependencyScope.LEGACY;
838         }
839     }
840 
841     @Override
842     public DependencyCollectionChecker getDependencyCollectionChecker() {
843         return dependencyCollectionChecker;
844     }
845 
846     /**
847      * Sets the dependency collection checker, may be {@code null}.
848      *
849      * @param dependencyCollectionChecker The dependency collection checker, may be {@code null}.
850      * @return The session for chaining, never {@code null}.
851      * @since 2.0.19
852      */
853     public DefaultRepositorySystemSession setDependencyCollectionChecker(
854             DependencyCollectionChecker dependencyCollectionChecker) {
855         this.dependencyCollectionChecker = dependencyCollectionChecker;
856         return this;
857     }
858 
859     /**
860      * Registers onSessionEnded handler, if able to.
861      *
862      * @param handler The handler to register
863      * @return Return {@code true} if registration was possible, otherwise {@code false}.
864      */
865     @Override
866     public boolean addOnSessionEndedHandler(Runnable handler) {
867         return onSessionEndedRegistrar.apply(handler);
868     }
869 
870     /**
871      * Marks this session as read-only such that any future attempts to call its mutators will fail with an exception.
872      * Marking an already read-only session as read-only has no effect. The session's data and cache remain writable
873      * though.
874      */
875     public void setReadOnly() {
876         readOnly = true;
877     }
878 
879     /**
880      * Verifies this instance state for mutation operations: mutated instance must not be read-only or closed.
881      */
882     private void verifyStateForMutation() {
883         if (readOnly) {
884             throw new IllegalStateException("repository system session is read-only");
885         }
886     }
887 
888     /**
889      * Simple "pass through" implementation of {@link ProxySelector} that simply returns what passed in
890      * {@link RemoteRepository} have set already, may return {@code null}.
891      */
892     static class PassthroughProxySelector implements ProxySelector {
893 
894         public static final ProxySelector INSTANCE = new PassthroughProxySelector();
895 
896         @Override
897         public Proxy getProxy(RemoteRepository repository) {
898             requireNonNull(repository, "repository cannot be null");
899             return repository.getProxy();
900         }
901     }
902 
903     /**
904      * Simple "null" implementation of {@link MirrorSelector} that returns {@code null} for any passed
905      * in {@link RemoteRepository}.
906      */
907     static class NullMirrorSelector implements MirrorSelector {
908 
909         public static final MirrorSelector INSTANCE = new NullMirrorSelector();
910 
911         @Override
912         public RemoteRepository getMirror(RemoteRepository repository) {
913             requireNonNull(repository, "repository cannot be null");
914             return null;
915         }
916     }
917 
918     /**
919      * Simple "pass through" implementation of {@link AuthenticationSelector} that simply returns what passed in
920      * {@link RemoteRepository} have set already, may return {@code null}.
921      */
922     static class PassthroughAuthenticationSelector implements AuthenticationSelector {
923 
924         public static final AuthenticationSelector INSTANCE = new PassthroughAuthenticationSelector();
925 
926         @Override
927         public Authentication getAuthentication(RemoteRepository repository) {
928             requireNonNull(repository, "repository cannot be null");
929             return repository.getAuthentication();
930         }
931     }
932 
933     /**
934      * Simple "null" implementation of {@link ArtifactTypeRegistry} that returns {@code null} for any type ID.
935      */
936     static final class NullArtifactTypeRegistry implements ArtifactTypeRegistry {
937 
938         public static final ArtifactTypeRegistry INSTANCE = new NullArtifactTypeRegistry();
939 
940         @Override
941         public ArtifactType get(String typeId) {
942             return null;
943         }
944     }
945 }