File: Metadata\ServiceDescriptorFactory.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Linq;
 
namespace Microsoft.Tools.ServiceModel.Svcutil.Metadata
{
    /// <summary>
    /// This class is intended for caching service descriptors that have already successfully resolved the service metadata.
    /// This is useful when authentication is required, like in UI-based scenarios. Once metadocs are downloaded they are cached in a service descriptor.
    /// Observe that it keeps a cache of all created descriptor instances regardless of state; it is intended for short-lived sessions.
    /// </summary>
    public class ServiceDescriptorFactory
    {
        private IHttpCredentialsProvider _userCredentialsProvider;
        private IClientCertificateProvider _clientCertificateProvider;
        private IServerCertificateValidationProvider _serverCertificateValidationProvider;
 
        private object _cacheLock = new object();
        private Dictionary<int, ServiceDescriptor> _cache = new Dictionary<int, ServiceDescriptor>();
 
        public ServiceDescriptorFactory(
            IHttpCredentialsProvider userCredentialsProvider,
            IClientCertificateProvider clientCertificateProvider,
            IServerCertificateValidationProvider serverCertificateValidationProvider)
        {
            _userCredentialsProvider = userCredentialsProvider;
            _clientCertificateProvider = clientCertificateProvider;
            _serverCertificateValidationProvider = serverCertificateValidationProvider;
        }
 
 
        /// <summary>
        /// Creates a ServiceDescriptor instance or retrieve an existing one that has imported its metadata already.
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        private ServiceDescriptor Get(MetadataDocumentLoader metadaDocLoader)
        {
            ServiceDescriptor serviceDescriptor;
            var key = metadaDocLoader.GetHashCode();
 
            lock (_cacheLock)
            {
                if (_cache.ContainsKey(key) && _cache[key].MetadataImported)
                {
                    serviceDescriptor = _cache[key];
                }
                else
                {
                    serviceDescriptor = CreateServiceDescriptor(metadaDocLoader);
                    _cache[key] = serviceDescriptor;
                }
            }
 
            return serviceDescriptor;
        }
 
        protected virtual ServiceDescriptor CreateServiceDescriptor(MetadataDocumentLoader metadaDocLoader)
        {
            return new ServiceDescriptor(metadaDocLoader);
        }
 
        protected virtual MetadataDocumentLoader CreateMetadataDocumentLoader(string uri, IHttpCredentialsProvider httpCredentialsProvider, IClientCertificateProvider clientCertificatesProvider, IServerCertificateValidationProvider serverCertificateValidationProvider)
        {
            return new MetadataDocumentLoader(uri, httpCredentialsProvider, clientCertificatesProvider, serverCertificateValidationProvider);
        }
 
        protected virtual MetadataDocumentLoader CreateMetadataDocumentLoader(IEnumerable<string> metadataFiles, bool resolveExternalDocuments, IHttpCredentialsProvider httpCredentialsProvider, IClientCertificateProvider clientCertificatesProvider, IServerCertificateValidationProvider serverCertificateValidationProvider)
        {
            return new MetadataDocumentLoader(metadataFiles, resolveExternalDocuments, httpCredentialsProvider, clientCertificatesProvider, serverCertificateValidationProvider);
        }
 
        public ServiceDescriptor Get(string metadataUri)
        {
            // validate the uri, this would throw if invalid.
            var metadaDocLoader = CreateMetadataDocumentLoader(metadataUri, _userCredentialsProvider, _clientCertificateProvider, _serverCertificateValidationProvider);
            return Get(metadaDocLoader);
        }
 
        public ServiceDescriptor Get(IEnumerable<string> metadataFiles)
        {
            // validate the uris, this would throw if invalid.
            var metadaDocLoader = CreateMetadataDocumentLoader(metadataFiles, false, _userCredentialsProvider, _clientCertificateProvider, _serverCertificateValidationProvider);
            return Get(metadaDocLoader);
        }
 
        /// <summary>
        /// Purges the cache.  Careful use of this method is required:
        /// This method removes any service descriptor that has not already downloaded its metadata successfully,
        /// so those currently downloading metadata (if any) will be removed from the cache.
        /// </summary>
        public void Purge()
        {
            lock (_cacheLock)
            {
                var removeKeys = _cache.Keys.Where((k) => !_cache[k].MetadataImported).ToList();
                removeKeys.ForEach((k) => _cache.Remove(k));
            }
        }
    }
}