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