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