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