< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.MtomMessageEncoderFactory
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/MtomMessageEncoder.cs
Line coverage
83%
Covered lines: 74
Uncovered lines: 15
Coverable lines: 89
Total lines: 708
Line coverage: 83.1%
Branch coverage
77%
Covered branches: 31
Total branches: 40
Branch coverage: 77.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)75%4492.85%
TakeStreamedWriter(...)83.33%6690%
ReturnStreamedWriter(...)100%11100%
TakeBufferedWriter(...)100%66100%
ReturnMessageWriter(...)100%11100%
TakeBufferedReader(...)100%66100%
ReturnBufferedData(...)100%11100%
TakeStreamedReader(...)50%141452.38%
ReturnStreamedReader(...)100%110%
GetSupportedEncodings()100%11100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/MtomMessageEncoder.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Globalization;
 6using System.IO;
 7using System.Text;
 8using System.Threading.Tasks;
 9using System.Xml;
 10
 11using CoreWCF.Description;
 12using CoreWCF.Diagnostics;
 13using CoreWCF.Runtime;
 14using CoreWCF.Runtime.Diagnostics;
 15using CoreWCF.Xml;
 16
 17namespace CoreWCF.Channels
 18{
 19    internal class MtomMessageEncoderFactory : MessageEncoderFactory
 20    {
 21        private MessageVersion _messageVersion;
 22        private Encoding _writeEncoding;
 23        private int _maxReadPoolSize;
 24        private int _maxWritePoolSize;
 25        private int _maxBufferSize;
 26        private XmlDictionaryReaderQuotas _readerQuotas;
 27
 28        // Pools used by MtomMessageEncoder
 29        private const int MaxPooledXmlReadersPerMessage = 2;
 30        private object _thisLock;
 31        private OnXmlDictionaryReaderClose _onStreamedReaderClose;
 32        // Double-checked locking pattern requires volatile for read/write synchronization
 33        private volatile SynchronizedPool<XmlDictionaryWriter> _streamedWriterPool;
 34        private volatile SynchronizedPool<XmlDictionaryReader> _streamedReaderPool;
 35        private volatile SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageData> _bufferedReaderPool;
 36        private volatile SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageWriter> _bufferedWriterPool;
 37        private volatile SynchronizedPool<RecycledMessageState> _recycledStatePool;
 38
 1339        public MtomMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWri
 40        {
 1341            _messageVersion = version;
 1342            _writeEncoding = writeEncoding;
 1343            _maxReadPoolSize = maxReadPoolSize;
 1344            _maxWritePoolSize = maxWritePoolSize;
 1345            _maxBufferSize = maxBufferSize;
 1346            _readerQuotas = quotas;
 1347            _thisLock = new object();
 1348            _onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader);
 1349            if (version.Envelope == EnvelopeVersion.Soap12)
 50            {
 1051                ContentEncodingMap = TextMessageEncoderFactory.Soap12Content;
 52            }
 353            else if (version.Envelope == EnvelopeVersion.Soap11)
 54            {
 355                ContentEncodingMap = TextMessageEncoderFactory.Soap11Content;
 56            }
 57            else
 58            {
 59                Fx.Assert("Invalid MessageVersion");
 060                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(Cu
 61            }
 62        }
 63
 2964        public override MessageEncoder Encoder => new MtomMessageEncoder(_messageVersion, _writeEncoding, _maxReadPoolSi
 65
 466        public override MessageVersion MessageVersion => _messageVersion;
 67
 1168        public int MaxWritePoolSize => _maxWritePoolSize;
 69
 2170        public int MaxReadPoolSize => _maxReadPoolSize;
 71
 172        public XmlDictionaryReaderQuotas ReaderQuotas => _readerQuotas;
 73
 174        public int MaxBufferSize => _maxBufferSize;
 75
 076        internal ContentEncoding[] ContentEncodingMap { get; }
 77
 78        internal XmlDictionaryWriter TakeStreamedWriter(Stream stream, string startInfo, string boundary, string startUr
 79        {
 180            if (_streamedWriterPool == null)
 81            {
 182                lock (_thisLock)
 83                {
 184                    if (_streamedWriterPool == null)
 85                    {
 186                        _streamedWriterPool = new SynchronizedPool<XmlDictionaryWriter>(MaxWritePoolSize);
 87                    }
 188                }
 89            }
 190            XmlDictionaryWriter xmlWriter = _streamedWriterPool.Take();
 191            if (xmlWriter == null)
 92            {
 193                xmlWriter = XmlMtomWriter.Create(stream, _writeEncoding, int.MaxValue, startInfo, boundary, startUri, wr
 94                // if (WcfEventSource.Instance.WritePoolMissIsEnabled())
 95                // {
 96                //     WcfEventSource.Instance.WritePoolMiss(xmlWriter.GetType().Name);
 97                // }
 98            }
 99            else
 100            {
 0101                ((IXmlMtomWriterInitializer)xmlWriter).SetOutput(stream, _writeEncoding, int.MaxValue, startInfo, bounda
 102            }
 1103            return xmlWriter;
 104        }
 105
 106        internal void ReturnStreamedWriter(XmlDictionaryWriter xmlWriter)
 107        {
 1108            xmlWriter.Close();
 1109            _streamedWriterPool.Return(xmlWriter);
 1110        }
 111
 112        internal MtomMessageEncoder.MtomBufferedMessageWriter TakeBufferedWriter(MtomMessageEncoder messageEncoder)
 113        {
 10114            if (_bufferedWriterPool == null)
 115            {
 10116                lock (_thisLock)
 117                {
 10118                    if (_bufferedWriterPool == null)
 119                    {
 10120                        _bufferedWriterPool = new SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageWriter>(MaxWrit
 121                    }
 10122                }
 123            }
 124
 10125            MtomMessageEncoder.MtomBufferedMessageWriter messageWriter = _bufferedWriterPool.Take();
 10126            if (messageWriter == null)
 127            {
 10128                messageWriter = new MtomMessageEncoder.MtomBufferedMessageWriter(messageEncoder);
 129                // if (WcfEventSource.Instance.WritePoolMissIsEnabled())
 130                // {
 131                //     WcfEventSource.Instance.WritePoolMiss(messageWriter.GetType().Name);
 132                // }
 133            }
 10134            return messageWriter;
 135        }
 136
 137        internal void ReturnMessageWriter(MtomMessageEncoder.MtomBufferedMessageWriter messageWriter)
 138        {
 10139            _bufferedWriterPool.Return(messageWriter);
 10140        }
 141
 142        internal MtomMessageEncoder.MtomBufferedMessageData TakeBufferedReader(MtomMessageEncoder messageEncoder)
 143        {
 10144            if (_bufferedReaderPool == null)
 145            {
 10146                lock (_thisLock)
 147                {
 10148                    if (_bufferedReaderPool == null)
 149                    {
 10150                        _bufferedReaderPool = new SynchronizedPool<MtomMessageEncoder.MtomBufferedMessageData>(MaxReadPo
 151                    }
 10152                }
 153            }
 10154            MtomMessageEncoder.MtomBufferedMessageData messageData = _bufferedReaderPool.Take();
 10155            if (messageData == null)
 156            {
 10157                messageData = new MtomMessageEncoder.MtomBufferedMessageData(messageEncoder, MaxPooledXmlReadersPerMessa
 158                // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 159                // {
 160                //     WcfEventSource.Instance.ReadPoolMiss(messageData.GetType().Name);
 161                // }
 162            }
 10163            return messageData;
 164        }
 165
 166        internal void ReturnBufferedData(MtomMessageEncoder.MtomBufferedMessageData messageData)
 167        {
 10168            _bufferedReaderPool.Return(messageData);
 10169        }
 170
 171        internal XmlReader TakeStreamedReader(Stream stream, string contentType, bool isMtomContentType)
 172        {
 1173            if (_streamedReaderPool == null)
 174            {
 1175                lock (_thisLock)
 176                {
 1177                    if (_streamedReaderPool == null)
 178                    {
 1179                        _streamedReaderPool = new SynchronizedPool<XmlDictionaryReader>(MaxReadPoolSize);
 180                    }
 1181                }
 182            }
 1183            XmlDictionaryReader xmlReader = _streamedReaderPool.Take();
 184            try
 185            {
 1186                if (contentType == null || isMtomContentType)
 187                {
 1188                    if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer)
 189                    {
 0190                        ((IXmlMtomReaderInitializer)xmlReader).SetInput(stream, MtomMessageEncoderFactory.GetSupportedEn
 191                    }
 192                    else
 193                    {
 1194                        xmlReader = XmlMtomReader.Create(stream, MtomMessageEncoderFactory.GetSupportedEncodings(), cont
 195                        // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 196                        // {
 197                        //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 198                        // }
 199                    }
 200                }
 201                else
 202                {
 0203                    if (xmlReader != null && xmlReader is IXmlTextReaderInitializer)
 204                    {
 0205                        ((IXmlTextReaderInitializer)xmlReader).SetInput(stream, TextMessageEncoderFactory.GetEncodingFro
 206                    }
 207                    else
 208                    {
 0209                        xmlReader = XmlDictionaryReader.CreateTextReader(stream, TextMessageEncoderFactory.GetEncodingFr
 210                        // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 211                        // {
 212                        //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 213                        // }
 214                    }
 215                }
 1216            }
 0217            catch (FormatException fe)
 218            {
 0219                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 0220                    SR.SFxErrorCreatingMtomReader, fe));
 221            }
 0222            catch (XmlException xe)
 223            {
 0224                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 0225                    SR.SFxErrorCreatingMtomReader, xe));
 226            }
 227
 1228            return xmlReader;
 229        }
 230
 231        internal void ReturnStreamedReader(XmlDictionaryReader xmlReader)
 232        {
 0233            _streamedReaderPool.Return(xmlReader);
 0234        }
 235
 236        internal SynchronizedPool<RecycledMessageState> RecycledStatePool
 237        {
 238            get
 239            {
 10240                if (_recycledStatePool == null)
 241                {
 10242                    lock (_thisLock)
 243                    {
 10244                        if (_recycledStatePool == null)
 245                        {
 10246                            _recycledStatePool = new SynchronizedPool<RecycledMessageState>(MaxReadPoolSize);
 247                        }
 10248                    }
 249                }
 10250                return _recycledStatePool;
 251            }
 252        }
 253
 254        public static Encoding[] GetSupportedEncodings()
 255        {
 11256            Encoding[] supported = TextEncoderDefaults.SupportedEncodings;
 11257            Encoding[] enc = new Encoding[supported.Length];
 11258            Array.Copy(supported, enc, supported.Length);
 11259            return enc;
 260        }
 261
 262    }
 263
 264    // Some notes:
 265    // The Encoding passed in is used for the SOAP envelope
 266    internal class MtomMessageEncoder : MessageEncoder, ITraceSourceStringProvider
 267    {
 268        private Encoding _writeEncoding;
 269        private string _contentType;
 270        private string _boundary;
 271        private MessageVersion _version;
 272        private static UriGenerator s_mimeBoundaryGenerator;
 273        private XmlDictionaryReaderQuotas _bufferedReadReaderQuotas;
 274
 275        private MtomMessageEncoderFactory _factory;
 276        private const string MtomMediaType = "multipart/related";
 277        private const string MtomContentType = MtomMediaType + "; type=\"application/xop+xml\"";
 278        private const string MtomStartUri = NamingHelper.DefaultNamespace + "0";
 279
 280        public MtomMessageEncoder(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolS
 281        {
 282            if (version == null)
 283                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 284            if (writeEncoding == null)
 285                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding));
 286
 287            _factory = factory;
 288            TextEncoderDefaults.ValidateEncoding(writeEncoding);
 289            _writeEncoding = writeEncoding;
 290
 291            MaxReadPoolSize = maxReadPoolSize;
 292            MaxWritePoolSize = maxWritePoolSize;
 293
 294            ReaderQuotas = new XmlDictionaryReaderQuotas();
 295            quotas.CopyTo(ReaderQuotas);
 296
 297            _bufferedReadReaderQuotas = EncoderHelpers.GetBufferedReadQuotas(ReaderQuotas);
 298            MaxBufferSize = maxBufferSize;
 299            _version = version;
 300            _contentType = GetContentType(out _boundary);
 301        }
 302
 303        private static UriGenerator MimeBoundaryGenerator
 304        {
 305            get
 306            {
 307                if (s_mimeBoundaryGenerator == null)
 308                    s_mimeBoundaryGenerator = new UriGenerator("uuid", "+");
 309                return s_mimeBoundaryGenerator;
 310            }
 311        }
 312
 313        public override string ContentType => _contentType;
 314
 315        public int MaxWritePoolSize { get; }
 316
 317        public int MaxReadPoolSize { get; }
 318
 319        public XmlDictionaryReaderQuotas ReaderQuotas { get; }
 320
 321        public int MaxBufferSize { get; }
 322
 323        public override string MediaType => MtomMediaType;
 324
 325        public override MessageVersion MessageVersion => _version;
 326
 327        internal bool IsMTOMContentType(string contentType)
 328        {
 329            // check for MTOM contentType: multipart/related; type=\"application/xop+xml\"
 330            return IsContentTypeSupported(contentType, ContentType, MediaType);
 331        }
 332
 333        internal bool IsTextContentType(string contentType)
 334        {
 335            // check for Text contentType: text/xml or application/soap+xml
 336            string textMediaType = TextMessageEncoderFactory.GetMediaType(_version);
 337            string textContentType = TextMessageEncoderFactory.GetContentType(textMediaType, _writeEncoding);
 338            return IsContentTypeSupported(contentType, textContentType, textMediaType);
 339        }
 340
 341        public override bool IsContentTypeSupported(string contentType)
 342        {
 343            if (contentType == null)
 344                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(contentType))
 345            return (IsMTOMContentType(contentType) || IsTextContentType(contentType));
 346        }
 347
 348        protected override bool IsCharSetSupported(string charSet)
 349        {
 350            if (charSet == null || charSet.Length == 0)
 351                return true;
 352
 353            Encoding tmp;
 354            return TextEncoderDefaults.TryGetEncoding(charSet, out tmp);
 355        }
 356
 357        private string GenerateStartInfoString()
 358        {
 359            return (_version.Envelope == EnvelopeVersion.Soap12) ? TextMessageEncoderFactory.Soap12MediaType : TextMessa
 360        }
 361
 362        public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
 363        {
 364            if (bufferManager == null)
 365                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bufferManager));
 366
 367            if (contentType == ContentType)
 368                contentType = null;
 369
 370            // if (WcfEventSource.Instance.MtomMessageDecodingStartIsEnabled())
 371            // {
 372            //     WcfEventSource.Instance.MtomMessageDecodingStart();
 373            // }
 374
 375            MtomBufferedMessageData messageData = _factory.TakeBufferedReader(this);
 376            messageData._contentType = contentType;
 377            messageData.Open(buffer, bufferManager);
 378            RecycledMessageState messageState = messageData.TakeMessageState();
 379            if (messageState == null)
 380                messageState = new RecycledMessageState();
 381            Message message = new BufferedMessage(messageData, messageState);
 382            message.Properties.Encoder = this;
 383            // if (MessageLogger.LogMessagesAtTransportLevel)
 384            //     MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
 385            //
 386            // if (WcfEventSource.Instance.MessageReadByEncoderIsEnabled() && buffer != null)
 387            // {
 388            //     WcfEventSource.Instance.MessageReadByEncoder(
 389            //         EventTraceActivityHelper.TryExtractActivity(message, true),
 390            //         buffer.Count,
 391            //         this);
 392            // }
 393
 394            return message;
 395        }
 396
 397        public override Task<Message> ReadMessageAsync(Stream stream, int maxSizeOfHeaders, string contentType)
 398        {
 399            if (stream == null)
 400                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)));
 401
 402            if (contentType == ContentType)
 403                contentType = null;
 404
 405            // if (WcfEventSource.Instance.MtomMessageDecodingStartIsEnabled())
 406            // {
 407            //     WcfEventSource.Instance.MtomMessageDecodingStart();
 408            // }
 409
 410            XmlReader reader = _factory.TakeStreamedReader(stream, contentType, contentType == null || IsMTOMContentType
 411            Message message = Message.CreateMessage(reader, maxSizeOfHeaders, _version);
 412            message.Properties.Encoder = this;
 413
 414            // if (WcfEventSource.Instance.StreamedMessageReadByEncoderIsEnabled())
 415            // {
 416            //     WcfEventSource.Instance.StreamedMessageReadByEncoder(EventTraceActivityHelper.TryExtractActivity(mess
 417            // }
 418            //
 419            // if (MessageLogger.LogMessagesAtTransportLevel)
 420            //     MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive);
 421            return Task.FromResult(message);
 422        }
 423
 424        public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager
 425        {
 426            return WriteMessageInternal(message, maxMessageSize, bufferManager, messageOffset, GenerateStartInfoString()
 427        }
 428
 429        // public override Task<ArraySegment<byte>> WriteMessageAsync(Message message, int maxMessageSize, BufferManager
 430        // {
 431        //     return Task.FromResult(WriteMessageInternal(message, maxMessageSize, bufferManager, messageOffset, Genera
 432        // }
 433
 434        private string GetContentType(out string boundary)
 435        {
 436            string startInfo = GenerateStartInfoString();
 437            boundary = MimeBoundaryGenerator.Next();
 438
 439            return FormatContentType(boundary, startInfo);
 440        }
 441
 442        internal string FormatContentType(string boundary, string startInfo)
 443        {
 444            return string.Format(CultureInfo.InvariantCulture,
 445                "{0};start=\"<{1}>\";boundary=\"{2}\";start-info=\"{3}\"",
 446                MtomContentType, MtomStartUri, boundary, startInfo);
 447        }
 448
 449        private ArraySegment<byte> WriteMessageInternal(Message message, int maxMessageSize, BufferManager bufferManager
 450        {
 451            bool writeMessageHeaders = true;
 452            if (message.Properties.TryGetValue("CoreWCF.Channel.MtomMessageEncoder.WriteMessageHeaders", out object bool
 453            {
 454                writeMessageHeaders = (bool)boolAsObject;
 455            }
 456
 457            if (message == null)
 458                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(message));
 459            if (bufferManager == null)
 460                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bufferManager));
 461            if (maxMessageSize < 0)
 462                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxMess
 463                                                    SRCommon.ValueMustBeNonNegative));
 464            if (messageOffset < 0 || messageOffset > maxMessageSize)
 465                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(message
 466                                                    SR.Format(SR.ValueMustBeInRange, 0, maxMessageSize)));
 467            ThrowIfMismatchedMessageVersion(message);
 468
 469            // EventTraceActivity eventTraceActivity = null;
 470            // if (WcfEventSource.Instance.MtomMessageEncodingStartIsEnabled())
 471            // {
 472            //     eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
 473            //     WcfEventSource.Instance.MtomMessageEncodingStart(eventTraceActivity);
 474            // }
 475
 476            message.Properties.Encoder = this;
 477
 478            MtomBufferedMessageWriter messageWriter = _factory.TakeBufferedWriter(this);
 479            messageWriter._startInfo = startInfo;
 480            messageWriter._boundary = boundary;
 481            messageWriter._startUri = startUri;
 482            messageWriter._writeMessageHeaders = writeMessageHeaders;
 483            messageWriter._maxSizeInBytes = maxMessageSize;
 484            ArraySegment<byte> messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessag
 485            _factory.ReturnMessageWriter(messageWriter);
 486
 487            // if (WcfEventSource.Instance.MessageWrittenByEncoderIsEnabled() && messageData != null)
 488            // {
 489            //     WcfEventSource.Instance.MessageWrittenByEncoder(
 490            //         eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message),
 491            //         messageData.Count,
 492            //         this);
 493            // }
 494            //
 495            // if (MessageLogger.LogMessagesAtTransportLevel)
 496            // {
 497            //     string contentType = null;
 498            //     if (boundary != null)
 499            //         contentType = FormatContentType(boundary, startInfo ?? GenerateStartInfoString());
 500            //
 501            //     XmlDictionaryReader xmlDictionaryReader = XmlMtomReader.Create(messageData.Array, messageData.Offset,
 502            //     MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend);
 503            // }
 504
 505            return messageData;
 506        }
 507
 508        // public override void WriteMessage(Message message, Stream stream)
 509        // {
 510        //     WriteMessageAsync(message, stream).WaitForCompletionNoSpin();
 511        // }
 512
 513        public override Task WriteMessageAsync(Message message, Stream stream)
 514        {
 515            return WriteMessageInternalAsync(message, stream, GenerateStartInfoString(), _boundary, MtomStartUri);
 516        }
 517
 518        // public override IAsyncResult BeginWriteMessage(Message message, Stream stream, AsyncCallback callback, object
 519        // {
 520        //     return WriteMessageAsync(message, stream).ToApm(callback, state);
 521        // }
 522        //
 523        // public override void EndWriteMessage(IAsyncResult result)
 524        // {
 525        //     result.ToApmEnd();
 526        // }
 527
 528        private async Task WriteMessageInternalAsync(Message message, Stream stream, string startInfo, string boundary, 
 529        {
 530            bool writeMessageHeaders = true;
 531            if (message.Properties.TryGetValue("CoreWCF.Channel.MtomMessageEncoder.WriteMessageHeaders", out object bool
 532            {
 533                writeMessageHeaders = (bool)boolAsObject;
 534            }
 535
 536            if (message == null)
 537                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message)));
 538            if (stream == null)
 539                throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)), message);
 540            ThrowIfMismatchedMessageVersion(message);
 541
 542            // EventTraceActivity eventTraceActivity = null;
 543            // if (WcfEventSource.Instance.MtomMessageEncodingStartIsEnabled())
 544            // {
 545            //     eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
 546            //     WcfEventSource.Instance.MtomMessageEncodingStart(eventTraceActivity);
 547            // }
 548
 549            message.Properties.Encoder = this;
 550            // if (MessageLogger.LogMessagesAtTransportLevel)
 551            //     MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend);
 552            XmlDictionaryWriter xmlWriter = _factory.TakeStreamedWriter(stream, startInfo, boundary, startUri, writeMess
 553            if (_writeEncoding.WebName == "utf-8")
 554            {
 555                await message.WriteMessageAsync(xmlWriter);
 556            }
 557            else
 558            {
 559                await xmlWriter.WriteStartDocumentAsync();
 560                await message.WriteMessageAsync(xmlWriter);
 561                await xmlWriter.WriteEndDocumentAsync();
 562            }
 563
 564            if (xmlWriter.SupportsAsync())
 565            {
 566                await xmlWriter.FlushAsync();
 567            }
 568            else
 569            {
 570                xmlWriter.Flush();
 571            }
 572            _factory.ReturnStreamedWriter(xmlWriter);
 573
 574            // if (WcfEventSource.Instance.StreamedMessageWrittenByEncoderIsEnabled())
 575            // {
 576            //     WcfEventSource.Instance.StreamedMessageWrittenByEncoder(eventTraceActivity ?? EventTraceActivityHelpe
 577            // }
 578        }
 579
 580        string ITraceSourceStringProvider.GetSourceString()
 581        {
 582            return GetTraceSourceString();
 583        }
 584
 585        internal class MtomBufferedMessageData : BufferedMessageData
 586        {
 587            private MtomMessageEncoder _messageEncoder;
 588            private Pool<XmlDictionaryReader> _readerPool;
 589            internal string _contentType;
 590            private OnXmlDictionaryReaderClose _onClose;
 591
 592            public MtomBufferedMessageData(MtomMessageEncoder messageEncoder, int maxReaderPoolSize)
 593                : base(messageEncoder._factory.RecycledStatePool)
 594            {
 595                _messageEncoder = messageEncoder;
 596                _readerPool = new Pool<XmlDictionaryReader>(maxReaderPoolSize);
 597                _onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed);
 598            }
 599
 600            public override MessageEncoder MessageEncoder => _messageEncoder;
 601
 602            public override XmlDictionaryReaderQuotas Quotas => _messageEncoder._bufferedReadReaderQuotas;
 603
 604            protected override void OnClosed()
 605            {
 606                _messageEncoder._factory.ReturnBufferedData(this);
 607            }
 608
 609            protected override XmlDictionaryReader TakeXmlReader()
 610            {
 611                try
 612                {
 613                    ArraySegment<byte> buffer = Buffer;
 614
 615                    XmlDictionaryReader xmlReader = _readerPool.Take();
 616                    if (_contentType == null || _messageEncoder.IsMTOMContentType(_contentType))
 617                    {
 618                        if (xmlReader != null && xmlReader is IXmlMtomReaderInitializer)
 619                        {
 620                            ((IXmlMtomReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, M
 621                        }
 622                        else
 623                        {
 624                            xmlReader = XmlMtomReader.Create(buffer.Array, buffer.Offset, buffer.Count, MtomMessageEncod
 625                            // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 626                            // {
 627                            //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 628                            // }
 629                        }
 630                    }
 631                    else
 632                    {
 633                        if (xmlReader != null && xmlReader is IXmlTextReaderInitializer)
 634                        {
 635                            ((IXmlTextReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, T
 636                        }
 637                        else
 638                        {
 639                            xmlReader = XmlDictionaryReader.CreateTextReader(buffer.Array, buffer.Offset, buffer.Count, 
 640                            // if (WcfEventSource.Instance.ReadPoolMissIsEnabled())
 641                            // {
 642                            //     WcfEventSource.Instance.ReadPoolMiss(xmlReader.GetType().Name);
 643                            // }
 644                        }
 645                    }
 646                    return xmlReader;
 647                }
 648                catch (FormatException fe)
 649                {
 650                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 651                        SR.SFxErrorCreatingMtomReader, fe));
 652                }
 653                catch (XmlException xe)
 654                {
 655                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
 656                        SR.SFxErrorCreatingMtomReader, xe));
 657                }
 658            }
 659
 660            protected override void ReturnXmlReader(XmlDictionaryReader xmlReader)
 661            {
 662                if (xmlReader != null)
 663                    _readerPool.Return(xmlReader);
 664            }
 665        }
 666
 667        internal class MtomBufferedMessageWriter : BufferedMessageWriter
 668        {
 669            private MtomMessageEncoder _messageEncoder;
 670            internal bool _writeMessageHeaders;
 671            internal string _startInfo;
 672            internal string _startUri;
 673            internal string _boundary;
 674            internal int _maxSizeInBytes = int.MaxValue;
 675            private XmlDictionaryWriter _writer;
 676
 677            public MtomBufferedMessageWriter(MtomMessageEncoder messageEncoder)
 678            {
 679                _messageEncoder = messageEncoder;
 680            }
 681
 682            protected override XmlDictionaryWriter TakeXmlWriter(Stream stream)
 683            {
 684                XmlDictionaryWriter returnedWriter = _writer;
 685                if (returnedWriter == null)
 686                {
 687                    returnedWriter = XmlMtomWriter.Create(stream, _messageEncoder._writeEncoding, _maxSizeInBytes, _star
 688                }
 689                else
 690                {
 691                    _writer = null;
 692                    ((IXmlMtomWriterInitializer)returnedWriter).SetOutput(stream, _messageEncoder._writeEncoding, _maxSi
 693                }
 694                if (_messageEncoder._writeEncoding.WebName != "utf-8")
 695                    returnedWriter.WriteStartDocument();
 696                return returnedWriter;
 697            }
 698
 699            protected override void ReturnXmlWriter(XmlDictionaryWriter writer)
 700            {
 701                writer.Close();
 702
 703                if (_writer == null)
 704                    _writer = writer;
 705            }
 706        }
 707    }
 708}