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