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