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