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