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