MtomMessageEncoder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / MtomMessageEncoder.cs / 1 / MtomMessageEncoder.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System.IO;
    using System.ServiceModel.Description; 
    using System.Collections.Generic; 
    using System.Runtime.Serialization;
    using System.ServiceModel; 
    using System.ServiceModel.Diagnostics;
    using System.Text;
    using System.Xml;
    using System.Globalization; 
    using System.Threading;
 
    class MtomMessageEncoderFactory : MessageEncoderFactory 
    {
        MtomMessageEncoder messageEncoder; 

        public MtomMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, int maxBufferSize, XmlDictionaryReaderQuotas quotas)
        {
            messageEncoder = new MtomMessageEncoder(version, writeEncoding, maxReadPoolSize, maxWritePoolSize, maxBufferSize, quotas); 
        }
 
        public override MessageEncoder Encoder 
        {
            get { return messageEncoder; } 
        }

        public override MessageVersion MessageVersion
        { 
            get { return messageEncoder.MessageVersion; }
        } 
 
        public int MaxWritePoolSize
        { 
            get { return messageEncoder.MaxWritePoolSize; }
        }

        public int MaxReadPoolSize 
        {
            get { return messageEncoder.MaxReadPoolSize; } 
        } 

        public XmlDictionaryReaderQuotas ReaderQuotas 
        {
            get
            {
                return messageEncoder.ReaderQuotas; 
            }
        } 
 
        public int MaxBufferSize
        { 
            get { return messageEncoder.MaxBufferSize; }
        }

        public static Encoding[] GetSupportedEncodings() 
        {
            Encoding[] supported = TextEncoderDefaults.SupportedEncodings; 
            Encoding[] enc = new Encoding[supported.Length]; 
            Array.Copy(supported, enc, supported.Length);
            return enc; 
        }

    }
 
    // Some notes:
    // The Encoding passed in is used for the SOAP envelope 
    class MtomMessageEncoder : MessageEncoder 
    {
        Encoding writeEncoding; 
        SynchronizedPool streamedWriterPool;
        SynchronizedPool streamedReaderPool;
        SynchronizedPool bufferedReaderPool;
        SynchronizedPool bufferedWriterPool; 
        SynchronizedPool recycledStatePool;
        object thisLock; 
        MessageVersion version; 
        const int maxPooledXmlReadersPerMessage = 2;
        int maxReadPoolSize; 
        int maxWritePoolSize;
        static UriGenerator mimeBoundaryGenerator;
        XmlDictionaryReaderQuotas readerQuotas;
        int maxBufferSize; 
        OnXmlDictionaryReaderClose onStreamedReaderClose;
 
        internal TextMessageEncoderFactory.ContentEncoding[] contentEncodingMap; 

        const string mtomMediaType = "multipart/related"; 
        const string mtomContentType = mtomMediaType + "; type=\"application/xop+xml\"";
        const string mtomStartUri = NamingHelper.DefaultNamespace + "0";

        public MtomMessageEncoder(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, int maxBufferSize, XmlDictionaryReaderQuotas quotas) 
        {
            if (version == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version"); 
            if (writeEncoding == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writeEncoding"); 

            TextEncoderDefaults.ValidateEncoding(writeEncoding);
            this.writeEncoding = writeEncoding;
 
            this.maxReadPoolSize = maxReadPoolSize;
            this.maxWritePoolSize = maxWritePoolSize; 
            this.readerQuotas = new XmlDictionaryReaderQuotas(); 
            quotas.CopyTo(this.readerQuotas);
            this.maxBufferSize = maxBufferSize; 
            this.onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader);

            this.thisLock = new object();
 
            if (version.Envelope == EnvelopeVersion.Soap12)
            { 
                this.contentEncodingMap = TextMessageEncoderFactory.Soap12Content; 
            }
            else if (version.Envelope == EnvelopeVersion.Soap11) 
            {
                this.contentEncodingMap = TextMessageEncoderFactory.Soap11Content;
            }
            else 
            {
                DiagnosticUtility.DebugAssert("Invalid MessageVersion"); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid MessageVersion"))); 
            }
 
            this.version = version;
        }

        static UriGenerator MimeBoundaryGenerator 
        {
            get 
            { 
                if (mimeBoundaryGenerator == null)
                    mimeBoundaryGenerator = new UriGenerator("uuid", "+"); 
                return mimeBoundaryGenerator;
            }
        }
 
        public override string ContentType
        { 
            get { return mtomContentType; } 
        }
 
        public int MaxWritePoolSize
        {
            get { return maxWritePoolSize; }
        } 

        public int MaxReadPoolSize 
        { 
            get { return maxReadPoolSize; }
        } 

        public XmlDictionaryReaderQuotas ReaderQuotas
        {
            get 
            {
                return readerQuotas; 
            } 
        }
 
        public int MaxBufferSize
        {
            get { return maxBufferSize; }
        } 

        public override string MediaType 
        { 
            get { return mtomMediaType; }
        } 

        public override MessageVersion MessageVersion
        {
            get { return version; } 
        }
 
        internal bool IsMTOMContentType(string contentType) 
        {
            // check for MTOM contentType: multipart/related; type=\"application/xop+xml\" 
            return IsContentTypeSupported(contentType, this.ContentType, this.MediaType);
        }

        internal bool IsTextContentType(string contentType) 
        {
            // check for Text contentType: text/xml or application/soap+xml 
            string textMediaType = TextMessageEncoderFactory.GetMediaType(version); 
            string textContentType = TextMessageEncoderFactory.GetContentType(textMediaType, writeEncoding);
            return IsContentTypeSupported(contentType, textContentType, textMediaType); 
        }

        public override bool IsContentTypeSupported(string contentType)
        { 
            if (contentType == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("contentType")); 
            return (IsMTOMContentType(contentType) || IsTextContentType(contentType)); 
        }
 
        internal override bool IsCharSetSupported(string charSet)
        {
            if (charSet == null || charSet.Length == 0)
                return true; 

            Encoding tmp; 
            return TextEncoderDefaults.TryGetEncoding(charSet, out tmp); 
        }
 
        string GenerateStartInfoString()
        {
            return (version.Envelope == EnvelopeVersion.Soap12) ? TextMessageEncoderFactory.Soap12MediaType : TextMessageEncoderFactory.Soap11MediaType;
        } 

        public override Message ReadMessage(ArraySegment buffer, BufferManager bufferManager, string contentType) 
        { 
            if (bufferManager == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bufferManager"); 

            if (contentType == this.ContentType)
                contentType = null;
 
            MtomBufferedMessageData messageData = TakeBufferedReader();
            messageData.ContentType = contentType; 
            messageData.Open(buffer, bufferManager); 
            RecycledMessageState messageState = messageData.TakeMessageState();
            if (messageState == null) 
                messageState = new RecycledMessageState();
            Message message = new BufferedMessage(messageData, messageState);
            message.Properties.Encoder = this;
            if (MessageLogger.LogMessagesAtTransportLevel) 
                MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
            return message; 
        } 

        public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) 
        {
            if (stream == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
 
            if (contentType == this.ContentType)
                contentType = null; 
 
            XmlReader reader = TakeStreamedReader(stream, contentType);
            Message message = Message.CreateMessage(reader, maxSizeOfHeaders, version); 
            message.Properties.Encoder = this;
            if (MessageLogger.LogMessagesAtTransportLevel)
                MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
            return message; 
        }
 
        public override ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset) 
        {
            return WriteMessage(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString(), null, null, true /*writeMessageHeaders*/); 
        }

        internal string GetContentType(out string boundary)
        { 
            string startInfo = GenerateStartInfoString();
            boundary = MimeBoundaryGenerator.Next(); 
 
            return FormatContentType(boundary, startInfo);
        } 

        internal string FormatContentType(string boundary, string startInfo)
        {
            return String.Format(CultureInfo.InvariantCulture, 
                "{0};start=\"<{1}>\";boundary=\"{2}\";start-info=\"{3}\"",
                mtomContentType, mtomStartUri, boundary, startInfo); 
        } 

        internal ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset, string boundary) 
        {
            return WriteMessage(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString(), boundary, mtomStartUri, false /*writeMessageHeaders*/);
        }
 
        ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset, string startInfo, string boundary, string startUri, bool writeMessageHeaders)
        { 
            if (message == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
            if (bufferManager == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bufferManager");
            if (maxMessageSize < 0)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxMessageSize", maxMessageSize,
                                                    SR.GetString(SR.ValueMustBeNonNegative))); 
            if (messageOffset < 0 || messageOffset > maxMessageSize)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("messageOffset", messageOffset, 
                                                    SR.GetString(SR.ValueMustBeInRange, 0, maxMessageSize))); 
            ThrowIfMismatchedMessageVersion(message);
            message.Properties.Encoder = this; 

            MtomBufferedMessageWriter messageWriter = TakeBufferedWriter();
            messageWriter.StartInfo = startInfo;
            messageWriter.Boundary = boundary; 
            messageWriter.StartUri = startUri;
            messageWriter.WriteMessageHeaders = writeMessageHeaders; 
            messageWriter.MaxSizeInBytes = maxMessageSize; 
            ArraySegment messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessageSize);
            ReturnMessageWriter(messageWriter); 
            if (MessageLogger.LogMessagesAtTransportLevel)
            {
                string contentType = null;
                if (boundary != null) 
                    contentType = FormatContentType(boundary, startInfo ?? GenerateStartInfoString());
 
                XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateMtomReader(messageData.Array, messageData.Offset, messageData.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, XmlDictionaryReaderQuotas.Max, int.MaxValue, null); 
                MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend);
            } 
            return messageData;
        }

        public override void WriteMessage(Message message, Stream stream) 
        {
            WriteMessage(message, stream, GenerateStartInfoString(), null, null, true /*writeMessageHeaders*/); 
        } 

        internal void WriteMessage(Message message, Stream stream, string boundary) 
        {
            WriteMessage(message, stream, GenerateStartInfoString(), boundary, mtomStartUri, false /*writeMessageHeaders*/);
        }
 
        void WriteMessage(Message message, Stream stream, string startInfo, string boundary, string startUri, bool writeMessageHeaders)
        { 
            if (message == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
            if (stream == null) 
                throw TraceUtility.ThrowHelperError(new ArgumentNullException("stream"), message);
            ThrowIfMismatchedMessageVersion(message);
            message.Properties.Encoder = this;
            if (MessageLogger.LogMessagesAtTransportLevel) 
                MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend);
            XmlDictionaryWriter xmlWriter = TakeStreamedWriter(stream, startInfo, boundary, startUri, writeMessageHeaders); 
            if (this.writeEncoding.WebName == "utf-8") 
            {
                message.WriteMessage(xmlWriter); 
            }
            else
            {
                xmlWriter.WriteStartDocument(); 
                message.WriteMessage(xmlWriter);
                xmlWriter.WriteEndDocument(); 
            } 
            xmlWriter.Flush();
            ReturnStreamedWriter(xmlWriter); 
        }

        XmlDictionaryWriter TakeStreamedWriter(Stream stream, string startInfo, string boundary, string startUri, bool writeMessageHeaders)
        { 
            if (streamedWriterPool == null)
            { 
                lock (thisLock) 
                {
                    if (streamedWriterPool == null) 
                    {
                        streamedWriterPool = new SynchronizedPool(maxWritePoolSize);
                    }
                } 
            }
            XmlDictionaryWriter xmlWriter = streamedWriterPool.Take(); 
            if (xmlWriter == null) 
            {
                xmlWriter = XmlDictionaryWriter.CreateMtomWriter(stream, this.writeEncoding, int.MaxValue, startInfo, boundary, startUri, writeMessageHeaders, false); 
            }
            else
            {
                ((IXmlMtomWriterInitializer)xmlWriter).SetOutput(stream, this.writeEncoding, int.MaxValue, startInfo, boundary, startUri, writeMessageHeaders, false); 
            }
            return xmlWriter; 
        } 

        void ReturnStreamedWriter(XmlDictionaryWriter xmlWriter) 
        {
            xmlWriter.Close();
            streamedWriterPool.Return(xmlWriter);
        } 

        MtomBufferedMessageWriter TakeBufferedWriter() 
        { 
            if (bufferedWriterPool == null)
            { 
                lock (thisLock)
                {
                    if (bufferedWriterPool == null)
                    { 
                        bufferedWriterPool = new SynchronizedPool(maxWritePoolSize);
                    } 
                } 
            }
 
            MtomBufferedMessageWriter messageWriter = bufferedWriterPool.Take();
            if (messageWriter == null)
                messageWriter = new MtomBufferedMessageWriter(this);
            return messageWriter; 
        }
 
        void ReturnMessageWriter(MtomBufferedMessageWriter messageWriter) 
        {
            bufferedWriterPool.Return(messageWriter); 
        }

        MtomBufferedMessageData TakeBufferedReader()
        { 
            if (bufferedReaderPool == null)
            { 
                lock (thisLock) 
                {
                    if (bufferedReaderPool == null) 
                    {
                        bufferedReaderPool = new SynchronizedPool(maxReadPoolSize);
                    }
                } 
            }
            MtomBufferedMessageData messageData = bufferedReaderPool.Take(); 
            if (messageData == null) 
                messageData = new MtomBufferedMessageData(this, maxPooledXmlReadersPerMessage);
            return messageData; 
        }

        void ReturnBufferedData(MtomBufferedMessageData messageData)
        { 
            bufferedReaderPool.Return(messageData);
        } 
 
        XmlReader TakeStreamedReader(Stream stream, string contentType)
        { 
            if (streamedReaderPool == null)
            {
                lock (thisLock)
                { 
                    if (streamedReaderPool == null)
                    { 
                        streamedReaderPool = new SynchronizedPool(maxReadPoolSize); 
                    }
                } 
            }
            XmlDictionaryReader xmlReader = streamedReaderPool.Take();
            try
            { 
                if (contentType == null || IsMTOMContentType(contentType))
                { 
                    if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer) 
                    {
                        ((IXmlMtomReaderInitializer)xmlReader).SetInput(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, this.readerQuotas, this.maxBufferSize, onStreamedReaderClose); 
                    }
                    else
                    {
                        xmlReader = XmlDictionaryReader.CreateMtomReader(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), contentType, this.readerQuotas, this.maxBufferSize, onStreamedReaderClose); 
                    }
                } 
                else 
                {
                    if (xmlReader != null && xmlReader is IXmlTextReaderInitializer) 
                    {
                        ((IXmlTextReaderInitializer)xmlReader).SetInput(stream, TextMessageEncoderFactory.GetEncodingFromContentType(contentType, this.contentEncodingMap), this.readerQuotas, onStreamedReaderClose);
                    }
                    else 
                    {
                        xmlReader = XmlDictionaryReader.CreateTextReader(stream, TextMessageEncoderFactory.GetEncodingFromContentType(contentType, this.contentEncodingMap), this.readerQuotas, onStreamedReaderClose); 
                    } 
                }
            } 
            catch (FormatException fe)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
                    SR.GetString(SR.SFxErrorCreatingMtomReader), fe)); 
            }
            catch (XmlException xe) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
                    SR.GetString(SR.SFxErrorCreatingMtomReader), xe)); 
            }

            return xmlReader;
        } 

        void ReturnStreamedReader(XmlDictionaryReader xmlReader) 
        { 
            streamedReaderPool.Return(xmlReader);
        } 

        SynchronizedPool RecycledStatePool
        {
            get 
            {
                if (recycledStatePool == null) 
                { 
                    lock (thisLock)
                    { 
                        if (recycledStatePool == null)
                        {
                            recycledStatePool = new SynchronizedPool(maxReadPoolSize);
                        } 
                    }
                } 
                return recycledStatePool; 
            }
        } 

        class MtomBufferedMessageData : BufferedMessageData
        {
            MtomMessageEncoder messageEncoder; 
            Pool readerPool;
            internal string ContentType; 
            OnXmlDictionaryReaderClose onClose; 

            public MtomBufferedMessageData(MtomMessageEncoder messageEncoder, int maxReaderPoolSize) 
                : base(messageEncoder.RecycledStatePool)
            {
                this.messageEncoder = messageEncoder;
                readerPool = new Pool(maxReaderPoolSize); 
                onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed);
            } 
 
            public override MessageEncoder MessageEncoder
            { 
                get { return messageEncoder; }
            }

            public override XmlDictionaryReaderQuotas Quotas 
            {
                get { return messageEncoder.ReaderQuotas; } 
            } 

            protected override void OnClosed() 
            {
                messageEncoder.ReturnBufferedData(this);
            }
 
            protected override XmlDictionaryReader TakeXmlReader()
            { 
                try 
                {
                    ArraySegment buffer = this.Buffer; 

                    XmlDictionaryReader xmlReader = readerPool.Take();
                    if (ContentType == null || messageEncoder.IsMTOMContentType(ContentType))
                    { 
                        if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer)
                        { 
                            ((IXmlMtomReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), ContentType, this.messageEncoder.ReaderQuotas, this.messageEncoder.MaxBufferSize, onClose); 
                        }
                        else 
                        {
                            xmlReader = XmlDictionaryReader.CreateMtomReader(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncoderFactory.GetSupportedEncodings(), ContentType, this.messageEncoder.ReaderQuotas, this.messageEncoder.MaxBufferSize, onClose);
                        }
                    } 
                    else
                    { 
                        if (xmlReader != null && xmlReader is IXmlTextReaderInitializer) 
                        {
                            ((IXmlTextReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, TextMessageEncoderFactory.GetEncodingFromContentType(ContentType, this.messageEncoder.contentEncodingMap), this.messageEncoder.ReaderQuotas, onClose); 
                        }
                        else
                        {
                            xmlReader = XmlDictionaryReader.CreateTextReader(buffer.Array, buffer.Offset, buffer.Count, TextMessageEncoderFactory.GetEncodingFromContentType(ContentType, this.messageEncoder.contentEncodingMap), this.messageEncoder.ReaderQuotas, onClose); 
                        }
                    } 
                    return xmlReader; 
                }
                catch (FormatException fe) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
                        SR.GetString(SR.SFxErrorCreatingMtomReader), fe));
                } 
                catch (XmlException xe)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( 
                        SR.GetString(SR.SFxErrorCreatingMtomReader), xe));
                } 
            }

            protected override void ReturnXmlReader(XmlDictionaryReader xmlReader)
            { 
                if (xmlReader != null)
                    readerPool.Return(xmlReader); 
            } 
        }
 
        class MtomBufferedMessageWriter : BufferedMessageWriter
        {
            MtomMessageEncoder messageEncoder;
            internal bool WriteMessageHeaders; 
            internal string StartInfo;
            internal string StartUri; 
            internal string Boundary; 
            internal int MaxSizeInBytes = int.MaxValue;
            XmlDictionaryWriter writer; 

            public MtomBufferedMessageWriter(MtomMessageEncoder messageEncoder)
            {
                this.messageEncoder = messageEncoder; 
            }
 
            protected override XmlDictionaryWriter TakeXmlWriter(Stream stream) 
            {
                XmlDictionaryWriter returnedWriter = writer; 
                if (returnedWriter == null)
                {
                    returnedWriter = XmlDictionaryWriter.CreateMtomWriter(stream, messageEncoder.writeEncoding, MaxSizeInBytes, StartInfo, Boundary, StartUri, WriteMessageHeaders, false);
                } 
                else
                { 
                    writer = null; 
                    ((IXmlMtomWriterInitializer)returnedWriter).SetOutput(stream, messageEncoder.writeEncoding, MaxSizeInBytes, StartInfo, Boundary, StartUri, WriteMessageHeaders, false);
                } 
                if (messageEncoder.writeEncoding.WebName != "utf-8")
                    returnedWriter.WriteStartDocument();
                return returnedWriter;
            } 

            protected override void ReturnXmlWriter(XmlDictionaryWriter writer) 
            { 
                writer.Close();
 
                if (this.writer == null)
                    this.writer = writer;
            }
        } 

    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK