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