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