File: System\ServiceModel\Description\MetadataImporter.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.ServiceModel.Description
{
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Runtime;
    using System.Security;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Configuration;
    using System.Xml;
 
    public abstract partial class MetadataImporter
    {
        readonly KeyedByTypeCollection<IPolicyImportExtension> policyExtensions;
        readonly Dictionary<XmlQualifiedName, ContractDescription> knownContracts = new Dictionary<XmlQualifiedName, ContractDescription>();
        readonly Collection<MetadataConversionError> errors = new Collection<MetadataConversionError>();
        readonly Dictionary<object, object> state = new Dictionary<object, object>();
 
        //prevent inheritance until we are ready to allow it.
        internal MetadataImporter()
            : this (null, MetadataImporterQuotas.Defaults)
        {
        }
 
        internal MetadataImporter(IEnumerable<IPolicyImportExtension> policyImportExtensions)
            : this (policyImportExtensions, MetadataImporterQuotas.Defaults)
        {
        }
 
        internal MetadataImporter(IEnumerable<IPolicyImportExtension> policyImportExtensions,
            MetadataImporterQuotas quotas)
        {
            if (quotas == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("quotas");
            }
 
            if (policyImportExtensions == null)
            {
                policyImportExtensions = LoadPolicyExtensionsFromConfig();
            }
 
            this.Quotas = quotas;
            this.policyExtensions = new KeyedByTypeCollection<IPolicyImportExtension>(policyImportExtensions);
        }
 
        public KeyedByTypeCollection<IPolicyImportExtension> PolicyImportExtensions
        {
            get { return this.policyExtensions; }
        }
 
        public Collection<MetadataConversionError> Errors
        {
            get { return this.errors; }
        }
 
        public Dictionary<object, object> State
        {
            get { return this.state; }
        }
 
        public Dictionary<XmlQualifiedName, ContractDescription> KnownContracts
        {
            get { return this.knownContracts; }
        }
 
        // Abstract Building Methods
        public abstract Collection<ContractDescription> ImportAllContracts();
        public abstract ServiceEndpointCollection ImportAllEndpoints();
 
        internal virtual XmlElement ResolvePolicyReference(string policyReference, XmlElement contextAssertion)
        {
            return null;
        }
        internal BindingElementCollection ImportPolicy(ServiceEndpoint endpoint, Collection<Collection<XmlElement>> policyAlternatives)
        {
            foreach (Collection<XmlElement> selectedPolicy in policyAlternatives)
            {
                BindingOnlyPolicyConversionContext policyConversionContext = new BindingOnlyPolicyConversionContext(endpoint, selectedPolicy);
 
                if (TryImportPolicy(policyConversionContext))
                {
                    return policyConversionContext.BindingElements;
                }
            }
            return null;
        }
 
        internal bool TryImportPolicy(PolicyConversionContext policyContext)
        {
            foreach (IPolicyImportExtension policyImporter in policyExtensions)
                try
                {
                    policyImporter.ImportPolicy(this, policyContext);
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                        throw;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateExtensionException(policyImporter, e));
                }
 
            if (policyContext.GetBindingAssertions().Count != 0)
                return false;
 
            foreach (OperationDescription operation in policyContext.Contract.Operations)
            {
                if (policyContext.GetOperationBindingAssertions(operation).Count != 0)
                    return false;
 
                foreach (MessageDescription message in operation.Messages)
                    if (policyContext.GetMessageBindingAssertions(message).Count != 0)
                        return false;
            }
 
            return true;
        }
 
        [Fx.Tag.SecurityNote(Critical = "uses ClientSection.UnsafeGetSection to get config in PT",
            Safe = "does not leak config object, just picks up extensions")]
        [SecuritySafeCritical]
        static Collection<IPolicyImportExtension> LoadPolicyExtensionsFromConfig()
        {
            return ClientSection.UnsafeGetSection().Metadata.LoadPolicyImportExtensions();
        }
 
        Exception CreateExtensionException(IPolicyImportExtension importer, Exception e)
        {
            string errorMessage = SR.GetString(SR.PolicyExtensionImportError, importer.GetType(), e.Message);
            return new InvalidOperationException(errorMessage, e);
        }
 
        internal class BindingOnlyPolicyConversionContext : PolicyConversionContext
        {
            static readonly PolicyAssertionCollection noPolicy = new PolicyAssertionCollection();
            readonly BindingElementCollection bindingElements = new BindingElementCollection();
            readonly PolicyAssertionCollection bindingPolicy;
 
            internal BindingOnlyPolicyConversionContext(ServiceEndpoint endpoint, IEnumerable<XmlElement> bindingPolicy)
                : base(endpoint)
            {
                this.bindingPolicy = new PolicyAssertionCollection(bindingPolicy);
            }
 
            public override BindingElementCollection BindingElements { get { return this.bindingElements; } }
 
            public override PolicyAssertionCollection GetBindingAssertions()
            {
                return this.bindingPolicy;
            }
 
            public override PolicyAssertionCollection GetOperationBindingAssertions(OperationDescription operation)
            {
                return noPolicy;
            }
 
            public override PolicyAssertionCollection GetMessageBindingAssertions(MessageDescription message)
            {
                return noPolicy;
            }
 
            public override PolicyAssertionCollection GetFaultBindingAssertions(FaultDescription fault)
            {
                return noPolicy;
            }
        }
    }
 
}