File: System\Runtime\Serialization\XsdDataContractImporter.cs
Project: ndp\cdf\src\WCF\Serialization\System.Runtime.Serialization.csproj (System.Runtime.Serialization)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
namespace System.Runtime.Serialization
{
    using System;
    using System.CodeDom;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Security;
    using System.ServiceModel.Diagnostics;
    using System.Xml;
    using System.Xml.Schema;
    using System.Runtime.Serialization.Diagnostics;
    using System.Security.Permissions;
 
    public class XsdDataContractImporter
    {
        ImportOptions options;
        CodeCompileUnit codeCompileUnit;
        DataContractSet dataContractSet;
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly XmlQualifiedName[] emptyTypeNameArray = new XmlQualifiedName[0];
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly XmlSchemaElement[] emptyElementArray = new XmlSchemaElement[0];
        XmlQualifiedName[] singleTypeNameArray;
        XmlSchemaElement[] singleElementArray;
 
        public XsdDataContractImporter()
        {
        }
 
        public XsdDataContractImporter(CodeCompileUnit codeCompileUnit)
        {
            this.codeCompileUnit = codeCompileUnit;
        }
 
        public ImportOptions Options
        {
            get { return options; }
            set { options = value; }
        }
 
 
        public CodeCompileUnit CodeCompileUnit
        {
            get
            {
                return GetCodeCompileUnit();
            }
        }
 
        CodeCompileUnit GetCodeCompileUnit()
        {
            if (codeCompileUnit == null)
                codeCompileUnit = new CodeCompileUnit();
            return codeCompileUnit;
        }
 
 
        DataContractSet DataContractSet
        {
            get
            {
 
                if (dataContractSet == null)
                {
                    dataContractSet = Options == null ? new DataContractSet(null, null, null) :
                                                        new DataContractSet(Options.DataContractSurrogate, Options.ReferencedTypes, Options.ReferencedCollectionTypes);
                }
                return dataContractSet;
            }
        }
 
        public void Import(XmlSchemaSet schemas)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            InternalImport(schemas, null, null, null);
        }
 
        public void Import(XmlSchemaSet schemas, ICollection<XmlQualifiedName> typeNames)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            if (typeNames == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("typeNames"));
 
            InternalImport(schemas, typeNames, emptyElementArray, emptyTypeNameArray);
        }
 
        public void Import(XmlSchemaSet schemas, XmlQualifiedName typeName)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            if (typeName == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("typeName"));
 
            SingleTypeNameArray[0] = typeName;
            InternalImport(schemas, SingleTypeNameArray, emptyElementArray, emptyTypeNameArray);
        }
 
        public XmlQualifiedName Import(XmlSchemaSet schemas, XmlSchemaElement element)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            if (element == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("element"));
 
            SingleTypeNameArray[0] = null;
            SingleElementArray[0] = element;
            InternalImport(schemas, emptyTypeNameArray, SingleElementArray, SingleTypeNameArray/*filled on return*/);
            return SingleTypeNameArray[0];
        }
 
 
        public bool CanImport(XmlSchemaSet schemas)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            return InternalCanImport(schemas, null, null, null);
        }
 
        public bool CanImport(XmlSchemaSet schemas, ICollection<XmlQualifiedName> typeNames)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            if (typeNames == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("typeNames"));
 
            return InternalCanImport(schemas, typeNames, emptyElementArray, emptyTypeNameArray);
        }
 
        public bool CanImport(XmlSchemaSet schemas, XmlQualifiedName typeName)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            if (typeName == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("typeName"));
 
            return InternalCanImport(schemas, new XmlQualifiedName[] { typeName }, emptyElementArray, emptyTypeNameArray);
        }
 
 
        public bool CanImport(XmlSchemaSet schemas, XmlSchemaElement element)
        {
            if (schemas == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("schemas"));
 
            if (element == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("element"));
 
            SingleTypeNameArray[0] = null;
            SingleElementArray[0] = element;
            return InternalCanImport(schemas, emptyTypeNameArray, SingleElementArray, SingleTypeNameArray);
        }
 
        public CodeTypeReference GetCodeTypeReference(XmlQualifiedName typeName)
        {
            DataContract dataContract = FindDataContract(typeName);
            CodeExporter codeExporter = new CodeExporter(DataContractSet, Options, GetCodeCompileUnit());
            return codeExporter.GetCodeTypeReference(dataContract);
        }
 
        public CodeTypeReference GetCodeTypeReference(XmlQualifiedName typeName, XmlSchemaElement element)
        {
            if (element == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("element"));
            if (typeName == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("typeName"));
            DataContract dataContract = FindDataContract(typeName);
            CodeExporter codeExporter = new CodeExporter(DataContractSet, Options, GetCodeCompileUnit());
#pragma warning suppress 56506 // Code Exporter will never be null
            return codeExporter.GetElementTypeReference(dataContract, element.IsNillable);
        }
 
        internal DataContract FindDataContract(XmlQualifiedName typeName)
        {
            if (typeName == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("typeName"));
 
            DataContract dataContract = DataContract.GetBuiltInDataContract(typeName.Name, typeName.Namespace);
            if (dataContract == null)
            {
                dataContract = DataContractSet[typeName];
                if (dataContract == null)
                    throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TypeHasNotBeenImported, typeName.Name, typeName.Namespace)));
            }
            return dataContract;
        }
 
        public ICollection<CodeTypeReference> GetKnownTypeReferences(XmlQualifiedName typeName)
        {
            if (typeName == null)
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("typeName"));
 
            DataContract dataContract = DataContract.GetBuiltInDataContract(typeName.Name, typeName.Namespace);
            if (dataContract == null)
            {
                dataContract = DataContractSet[typeName];
                if (dataContract == null)
                    throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TypeHasNotBeenImported, typeName.Name, typeName.Namespace)));
            }
 
            CodeExporter codeExporter = new CodeExporter(DataContractSet, Options, GetCodeCompileUnit());
            return codeExporter.GetKnownTypeReferences(dataContract);
        }
 
        XmlQualifiedName[] SingleTypeNameArray
        {
            get
            {
                if (singleTypeNameArray == null)
                    singleTypeNameArray = new XmlQualifiedName[1];
                return singleTypeNameArray;
            }
        }
 
        XmlSchemaElement[] SingleElementArray
        {
            get
            {
                if (singleElementArray == null)
                    singleElementArray = new XmlSchemaElement[1];
                return singleElementArray;
            }
        }
 
        [Fx.Tag.SecurityNote(Critical = "Critical because it calls the security critical method CodeExporter.Export(..).",
            Safe = "Safe because it does a Demand for FullTrust.")]
        [SecuritySafeCritical]
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        void InternalImport(XmlSchemaSet schemas, ICollection<XmlQualifiedName> typeNames, ICollection<XmlSchemaElement> elements, XmlQualifiedName[] elementTypeNames/*filled on return*/)
        {
            if (DiagnosticUtility.ShouldTraceInformation)
            {
                TraceUtility.Trace(TraceEventType.Information, TraceCode.XsdImportBegin, SR.GetString(SR.TraceCodeXsdImportBegin));
            }
 
            DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
            try
            {
                SchemaImporter schemaImporter = new SchemaImporter(schemas, typeNames, elements, elementTypeNames/*filled on return*/, DataContractSet, ImportXmlDataType);
                schemaImporter.Import();
 
                CodeExporter codeExporter = new CodeExporter(DataContractSet, Options, GetCodeCompileUnit());
                codeExporter.Export();
            }
            catch (Exception ex)
            {
                if (Fx.IsFatal(ex))
                {
                    throw;
                }
                dataContractSet = oldValue;
                TraceImportError(ex);
                throw;
            }
 
            if (DiagnosticUtility.ShouldTraceInformation)
            {
                TraceUtility.Trace(TraceEventType.Information, TraceCode.XsdImportEnd, SR.GetString(SR.TraceCodeXsdImportEnd));
            }
        }
 
        bool ImportXmlDataType
        {
            get
            {
                return this.Options == null ? false : this.Options.ImportXmlType;
            }
        }
 
        void TraceImportError(Exception exception)
        {
            if (DiagnosticUtility.ShouldTraceError)
            {
                TraceUtility.Trace(TraceEventType.Error, TraceCode.XsdImportError, SR.GetString(SR.TraceCodeXsdImportError), null, exception);
            }
        }
 
 
        bool InternalCanImport(XmlSchemaSet schemas, ICollection<XmlQualifiedName> typeNames, ICollection<XmlSchemaElement> elements, XmlQualifiedName[] elementTypeNames)
        {
            DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
            try
            {
                SchemaImporter schemaImporter = new SchemaImporter(schemas, typeNames, elements, elementTypeNames, DataContractSet, ImportXmlDataType);
                schemaImporter.Import();
                return true;
            }
            catch (InvalidDataContractException)
            {
                dataContractSet = oldValue;
                return false;
            }
            catch (Exception ex)
            {
                if (Fx.IsFatal(ex))
                {
                    throw;
                }
                dataContractSet = oldValue;
                TraceImportError(ex);
                throw;
            }
        }
 
    }
 
}