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