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