< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.TextMessageEncoderFactory
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/TextMessageEncoderFactory.cs
Line coverage
80%
Covered lines: 216
Uncovered lines: 54
Coverable lines: 270
Total lines: 776
Line coverage: 80%
Branch coverage
69%
Covered branches: 103
Total branches: 148
Branch coverage: 69.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%11100%
.ctor(...)100%11100%
GetSupportedEncodings()100%11100%
GetMediaType(...)83.33%6677.77%
GetContentType(...)100%11100%
GetContentEncodingMap(...)100%22100%
GetEncodingFromContentType(...)56.81%444450%
TryGetEncodingFromCharSet(...)50%4475%
.ctor(...)50%101079.16%
IsUTF8Encoding(...)100%11100%
IsCharSetSupported(...)50%8866.66%
IsContentTypeSupported(...)71.42%141471.42%
ReadMessage(...)75%4490.9%
ReadMessageAsync(...)50%2283.33%
WriteMessage(...)50%101062.5%
WriteMessageAsync()50%6668.75%
TakeStreamedWriter(...)100%66100%
ReturnStreamedWriter(...)100%11100%
TakeBufferedWriter()100%66100%
ReturnMessageWriter(...)100%11100%
TakeStreamedReader(...)83.33%6690%
ReturnStreamedReader(...)100%110%
CreateWriter(...)100%110%
TakeBufferedReader()100%66100%
ReturnBufferedData(...)100%11100%
.ctor(...)100%11100%
OnClosed()100%11100%
TakeXmlReader()100%22100%
ReturnXmlReader(...)100%22100%
.ctor(...)100%11100%
OnWriteStartMessage(...)50%2266.66%
OnWriteEndMessage(...)50%2266.66%
TakeXmlWriter(...)50%2266.66%
ReturnXmlWriter(...)100%11100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/TextMessageEncoderFactory.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.Diagnostics.Contracts;
 6using System.Globalization;
 7using System.IO;
 8using System.Net.Http.Headers;
 9using System.Text;
 10using System.Threading.Tasks;
 11using System.Xml;
 12using CoreWCF.Diagnostics;
 13using CoreWCF.Runtime;
 14
 15namespace CoreWCF.Channels
 16{
 17    internal class TextMessageEncoderFactory : MessageEncoderFactory
 18    {
 19        private readonly TextMessageEncoder _messageEncoder;
 20        //internal static ContentEncoding[] Soap11Content = GetContentEncodingMap(MessageVersion.Soap11WSAddressing10);
 21        // I believe replacing Soap11WSAddressing10 with Soap11 should work
 722        internal static ContentEncoding[] Soap11Content = GetContentEncodingMap(MessageVersion.Soap11);
 723        internal static ContentEncoding[] Soap12Content = GetContentEncodingMap(MessageVersion.Soap12WSAddressing10);
 724        internal static ContentEncoding[] SoapNoneContent = GetContentEncodingMap(MessageVersion.None);
 25        internal const string Soap11MediaType = "text/xml";
 26        internal const string Soap12MediaType = "application/soap+xml";
 27        private const string XmlMediaType = "application/xml";
 28
 77029        public TextMessageEncoderFactory(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWri
 30        {
 77031            _messageEncoder = new TextMessageEncoder(version, writeEncoding, maxReadPoolSize, maxWritePoolSize, quotas);
 77032        }
 33
 34        public override MessageEncoder Encoder
 35        {
 388236            get { return _messageEncoder; }
 37        }
 38
 39        public override MessageVersion MessageVersion
 40        {
 641            get { return _messageEncoder.MessageVersion; }
 42        }
 43
 44        public int MaxWritePoolSize
 45        {
 046            get { return _messageEncoder.MaxWritePoolSize; }
 47        }
 48
 49        public int MaxReadPoolSize
 50        {
 051            get { return _messageEncoder.MaxReadPoolSize; }
 52        }
 53
 54        public static Encoding[] GetSupportedEncodings()
 55        {
 2156            Encoding[] supported = TextEncoderDefaults.SupportedEncodings;
 2157            Encoding[] enc = new Encoding[supported.Length];
 2158            Array.Copy(supported, enc, supported.Length);
 2159            return enc;
 60        }
 61
 62        public XmlDictionaryReaderQuotas ReaderQuotas
 63        {
 64            get
 65            {
 066                return _messageEncoder.ReaderQuotas;
 67            }
 68        }
 69
 70        internal static string GetMediaType(MessageVersion version)
 71        {
 72            string mediaType;
 79173            if (version.Envelope == EnvelopeVersion.Soap12)
 74            {
 46275                mediaType = Soap12MediaType;
 76            }
 32977            else if (version.Envelope == EnvelopeVersion.Soap11)
 78            {
 31879                mediaType = Soap11MediaType;
 80            }
 1181            else if (version.Envelope == EnvelopeVersion.None)
 82            {
 1183                mediaType = XmlMediaType;
 84            }
 85            else
 86            {
 087                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 088                    SR.Format(SR.EnvelopeVersionNotSupported, version.Envelope)));
 89            }
 79190            return mediaType;
 91        }
 92
 93        internal static string GetContentType(string mediaType, Encoding encoding)
 94        {
 83395            return string.Format(CultureInfo.InvariantCulture, "{0}; charset={1}", mediaType, TextEncoderDefaults.Encodi
 96        }
 97
 98        private static ContentEncoding[] GetContentEncodingMap(MessageVersion version)
 99        {
 21100            Encoding[] readEncodings = GetSupportedEncodings();
 21101            string media = GetMediaType(version);
 21102            ContentEncoding[] map = new ContentEncoding[readEncodings.Length];
 168103            for (int i = 0; i < readEncodings.Length; i++)
 104            {
 63105                ContentEncoding contentEncoding = new ContentEncoding
 63106                {
 63107                    contentType = GetContentType(media, readEncodings[i]),
 63108                    encoding = readEncodings[i]
 63109                };
 63110                map[i] = contentEncoding;
 111            }
 21112            return map;
 113        }
 114
 115        internal static Encoding GetEncodingFromContentType(string contentType, ContentEncoding[] contentMap)
 116        {
 3312117            if (contentType == null)
 118            {
 2711119                return null;
 120            }
 121
 122            // Check for known/expected content types
 1226123            for (int i = 0; i < contentMap.Length; i++)
 124            {
 609125                if (contentMap[i].contentType == contentType)
 126                {
 597127                    return contentMap[i].encoding;
 128                }
 129            }
 130
 131            // then some heuristic matches (since System.Mime.ContentType is a performance hit)
 132            // start by looking for a parameter.
 133
 134            // If none exists, we don't have an encoding
 4135            int semiColonIndex = contentType.IndexOf(';');
 4136            if (semiColonIndex == -1)
 137            {
 1138                return null;
 139            }
 140
 141            // optimize for charset being the first parameter
 3142            int charsetValueIndex = -1;
 143
 144            // for Indigo scenarios, we'll have "; charset=", so check for the c
 3145            if ((contentType.Length > semiColonIndex + 11) // need room for parameter + charset + '='
 3146                && contentType[semiColonIndex + 2] == 'c'
 3147                && string.Compare("charset=", 0, contentType, semiColonIndex + 2, 8, StringComparison.OrdinalIgnoreCase)
 148            {
 3149                charsetValueIndex = semiColonIndex + 10;
 150            }
 151            else
 152            {
 153                // look for charset= somewhere else in the message
 0154                int paramIndex = contentType.IndexOf("charset=", semiColonIndex + 1, StringComparison.OrdinalIgnoreCase)
 0155                if (paramIndex != -1)
 156                {
 157                    // validate there's only whitespace or semi-colons beforehand
 0158                    for (int i = paramIndex - 1; i >= semiColonIndex; i--)
 159                    {
 0160                        if (contentType[i] == ';')
 161                        {
 0162                            charsetValueIndex = paramIndex + 8;
 0163                            break;
 164                        }
 165
 0166                        if (contentType[i] == '\n')
 167                        {
 0168                            if (i == semiColonIndex || contentType[i - 1] != '\r')
 169                            {
 170                                break;
 171                            }
 172
 0173                            i--;
 0174                            continue;
 175                        }
 176
 0177                        if (contentType[i] != ' '
 0178                            && contentType[i] != '\t')
 179                        {
 180                            break;
 181                        }
 182                    }
 183                }
 184            }
 185
 186            string charSet;
 187            Encoding enc;
 188
 189            // we have a possible charset value. If it's easy to parse, do so
 3190            if (charsetValueIndex != -1)
 191            {
 192                // get the next semicolon
 3193                semiColonIndex = contentType.IndexOf(';', charsetValueIndex);
 3194                if (semiColonIndex == -1)
 195                {
 2196                    charSet = contentType.Substring(charsetValueIndex);
 197                }
 198                else
 199                {
 1200                    charSet = contentType.Substring(charsetValueIndex, semiColonIndex - charsetValueIndex);
 201                }
 202
 203                // and some minimal quote stripping
 3204                if (charSet.Length > 2 && charSet[0] == '"' && charSet[charSet.Length - 1] == '"')
 205                {
 1206                    charSet = charSet.Substring(1, charSet.Length - 2);
 207                }
 208
 3209                if (TryGetEncodingFromCharSet(charSet, out enc))
 210                {
 3211                    return enc;
 212                }
 213            }
 214
 215            // our quick heuristics failed. fall back to System.Net
 216            try
 217            {
 0218                MediaTypeHeaderValue parsedContentType = MediaTypeHeaderValue.Parse(contentType);
 0219                charSet = parsedContentType.CharSet;
 0220            }
 0221            catch (FormatException e)
 222            {
 0223                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.EncoderBadContentType
 224            }
 225
 0226            if (TryGetEncodingFromCharSet(charSet, out enc))
 227            {
 0228                return enc;
 229            }
 230
 0231            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.Format(SR.EncoderUnrecogn
 232        }
 233
 234        internal static bool TryGetEncodingFromCharSet(string charSet, out Encoding encoding)
 235        {
 3236            encoding = null;
 3237            if (charSet == null || charSet.Length == 0)
 238            {
 0239                return true;
 240            }
 241
 3242            return TextEncoderDefaults.TryGetEncoding(charSet, out encoding);
 243        }
 244
 245        private class TextMessageEncoder : MessageEncoder
 246        {
 247
 248            // Double-checked locking pattern requires volatile for read/write synchronization
 249            private volatile SynchronizedPool<XmlDictionaryWriter> _streamedWriterPool;
 250            private volatile SynchronizedPool<XmlDictionaryReader> _streamedReaderPool;
 251            private volatile SynchronizedPool<UTF8BufferedMessageData> _bufferedReaderPool;
 252            private volatile SynchronizedPool<TextBufferedMessageWriter> _bufferedWriterPool;
 253            private volatile SynchronizedPool<RecycledMessageState> _recycledStatePool;
 254            private readonly string _contentType;
 255            private readonly string _mediaType;
 256            private readonly Encoding _writeEncoding;
 257            private readonly MessageVersion _version;
 258            private readonly bool _optimizeWriteForUTF8;
 259            private const int maxPooledXmlReadersPerMessage = 2;
 260            private readonly XmlDictionaryReaderQuotas _bufferedReadReaderQuotas;
 261            private readonly OnXmlDictionaryReaderClose _onStreamedReaderClose;
 262            private readonly ContentEncoding[] _contentEncodingMap;
 263
 770264            public TextMessageEncoder(MessageVersion version, Encoding writeEncoding, int maxReadPoolSize, int maxWriteP
 265            {
 770266                if (writeEncoding == null)
 267                {
 0268                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding));
 269                }
 270
 770271                TextEncoderDefaults.ValidateEncoding(writeEncoding);
 770272                _writeEncoding = writeEncoding;
 770273                _optimizeWriteForUTF8 = IsUTF8Encoding(writeEncoding);
 274
 770275                ThisLock = new object();
 276
 770277                _version = version ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 770278                MaxReadPoolSize = maxReadPoolSize;
 770279                MaxWritePoolSize = maxWritePoolSize;
 280
 770281                ReaderQuotas = new XmlDictionaryReaderQuotas();
 770282                quotas.CopyTo(ReaderQuotas);
 283
 770284                _bufferedReadReaderQuotas = EncoderHelpers.GetBufferedReadQuotas(ReaderQuotas);
 285
 770286                _onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader);
 287
 770288                _mediaType = GetMediaType(version);
 770289                _contentType = GetContentType(_mediaType, writeEncoding);
 770290                if (version.Envelope == EnvelopeVersion.Soap12)
 291                {
 455292                    _contentEncodingMap = Soap12Content;
 293                }
 315294                else if (version.Envelope == EnvelopeVersion.Soap11)
 295                {
 311296                    _contentEncodingMap = Soap11Content;
 297                }
 4298                else if (version.Envelope == EnvelopeVersion.None)
 299                {
 4300                    _contentEncodingMap = SoapNoneContent;
 301                }
 302                else
 303                {
 0304                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 0305                        SR.Format(SR.EnvelopeVersionNotSupported, version.Envelope)));
 306                }
 307            }
 308
 309            private static bool IsUTF8Encoding(Encoding encoding)
 310            {
 770311                return encoding.WebName == "utf-8";
 312            }
 313
 314            public override string ContentType
 315            {
 1204316                get { return _contentType; }
 317            }
 318
 530319            public int MaxWritePoolSize { get; }
 320
 1018321            public int MaxReadPoolSize { get; }
 322
 4079323            public XmlDictionaryReaderQuotas ReaderQuotas { get; }
 324
 325            public override string MediaType
 326            {
 602327                get { return _mediaType; }
 328            }
 329
 330            public override MessageVersion MessageVersion
 331            {
 2453332                get { return _version; }
 333            }
 334
 1549335            private object ThisLock { get; }
 336
 337
 338            protected override bool IsCharSetSupported(string charSet)
 339            {
 340                Encoding tmp;
 2341                if (!TextEncoderDefaults.TryGetEncoding(charSet, out tmp))
 342                {
 343                    // GetEncodingFromContentType supports charset with quotes (by simply stripping them) so we do the s
 344                    // This also gives us parity with Desktop WCF behavior
 1345                    if (charSet.Length > 2 && charSet[0] == '"' && charSet[charSet.Length - 1] == '"')
 346                    {
 1347                        charSet = charSet.Substring(1, charSet.Length - 2);
 1348                        return TextEncoderDefaults.TryGetEncoding(charSet, out tmp);
 349                    }
 0350                    return false;
 351                }
 352
 1353                return true;
 354            }
 355
 356            public override bool IsContentTypeSupported(string contentType)
 357            {
 602358                if (contentType == null)
 359                {
 0360                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(contentType));
 361                }
 362
 602363                if (base.IsContentTypeSupported(contentType))
 364                {
 599365                    return true;
 366                }
 367
 368                // we support a few extra content types for "none"
 3369                if (MessageVersion == MessageVersion.None)
 370                {
 371                    const string rss1MediaType = "text/xml";
 372                    const string rss2MediaType = "application/rss+xml";
 373                    const string atomMediaType = "application/atom+xml";
 374                    const string htmlMediaType = "text/html";
 375
 2376                    if (IsContentTypeSupported(contentType, rss1MediaType, rss1MediaType))
 377                    {
 1378                        return true;
 379                    }
 1380                    if (IsContentTypeSupported(contentType, rss2MediaType, rss2MediaType))
 381                    {
 0382                        return true;
 383                    }
 1384                    if (IsContentTypeSupported(contentType, htmlMediaType, htmlMediaType))
 385                    {
 0386                        return true;
 387                    }
 1388                    if (IsContentTypeSupported(contentType, atomMediaType, atomMediaType))
 389                    {
 0390                        return true;
 391                    }
 392                    // application/xml checked by base method
 393                }
 394
 2395                return false;
 396            }
 397
 398            public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentTy
 399            {
 773400                if (bufferManager == null)
 401                {
 0402                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bufferManager));
 403                }
 404
 405                Message message;
 406
 773407                UTF8BufferedMessageData messageData = TakeBufferedReader();
 773408                messageData.Encoding = GetEncodingFromContentType(contentType, _contentEncodingMap);
 773409                messageData.Open(buffer, bufferManager);
 773410                RecycledMessageState messageState = messageData.TakeMessageState();
 773411                if (messageState == null)
 412                {
 531413                    messageState = new RecycledMessageState();
 414                }
 415
 773416                message = new BufferedMessage(messageData, messageState);
 417
 773418                message.Properties.Encoder = this;
 419
 773420                return message;
 421            }
 422
 423            public override Task<Message> ReadMessageAsync(Stream stream, int maxSizeOfHeaders, string contentType)
 424            {
 2539425                if (stream == null)
 426                {
 0427                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)))
 428                }
 429
 2539430                XmlReader reader = TakeStreamedReader(stream, GetEncodingFromContentType(contentType, _contentEncodingMa
 2537431                Message message = Message.CreateMessage(reader, maxSizeOfHeaders, _version);
 2524432                message.Properties.Encoder = this;
 433
 2524434                return Task.FromResult(message);
 435            }
 436
 437            public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferMan
 438            {
 666439                if (message == null)
 440                {
 0441                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message))
 442                }
 443
 666444                if (bufferManager == null)
 445                {
 0446                    throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(bufferManager)), message);
 447                }
 448
 666449                if (maxMessageSize < 0)
 450                {
 0451                    throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxMessageSize), maxMessa
 0452                                                                SRCommon.ValueMustBeNonNegative), message);
 453                }
 454
 666455                if (messageOffset < 0 || messageOffset > maxMessageSize)
 456                {
 0457                    throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(messageOffset), messageOf
 0458                                                    SR.Format(SR.ValueMustBeInRange, 0, maxMessageSize)), message);
 459                }
 460
 666461                ThrowIfMismatchedMessageVersion(message);
 462
 666463                message.Properties.Encoder = this;
 666464                TextBufferedMessageWriter messageWriter = TakeBufferedWriter();
 666465                ArraySegment<byte> messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMe
 666466                ReturnMessageWriter(messageWriter);
 467
 666468                return messageData;
 469            }
 470
 471            public override async Task WriteMessageAsync(Message message, Stream stream)
 472            {
 826473                if (message == null)
 474                {
 0475                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(message));
 476                }
 477
 826478                if (stream == null)
 479                {
 0480                    throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)), message);
 481                }
 482
 826483                ThrowIfMismatchedMessageVersion(message);
 484
 826485                message.Properties.Encoder = this;
 826486                XmlDictionaryWriter xmlWriter = TakeStreamedWriter(stream);
 826487                if (_optimizeWriteForUTF8)
 488                {
 826489                    await message.WriteMessageAsync(xmlWriter);
 490                }
 491                else
 492                {
 0493                    xmlWriter.WriteStartDocument();
 0494                    await message.WriteMessageAsync(xmlWriter);
 0495                    xmlWriter.WriteEndDocument();
 496                }
 497
 825498                xmlWriter.Flush();
 825499                ReturnStreamedWriter(xmlWriter);
 825500                await stream.FlushAsync();
 825501            }
 502
 503            private XmlDictionaryWriter TakeStreamedWriter(Stream stream)
 504            {
 826505                if (_streamedWriterPool == null)
 506                {
 101507                    lock (ThisLock)
 508                    {
 101509                        if (_streamedWriterPool == null)
 510                        {
 101511                            _streamedWriterPool = new SynchronizedPool<XmlDictionaryWriter>(MaxWritePoolSize);
 512                        }
 101513                    }
 514                }
 826515                XmlDictionaryWriter xmlWriter = _streamedWriterPool.Take();
 826516                if (xmlWriter == null)
 517                {
 826518                    xmlWriter = XmlDictionaryWriter.CreateTextWriter(stream, _writeEncoding, false);
 519                }
 520                // TODO: Use the reinitialization API's once moved to .Net Standard 2.0
 521                //else
 522                //{
 523                //    ((IXmlTextWriterInitializer)xmlWriter).SetOutput(stream, this.writeEncoding, false);
 524                //}
 826525                return xmlWriter;
 526            }
 527
 528            private void ReturnStreamedWriter(XmlWriter xmlWriter)
 529            {
 825530                xmlWriter.Dispose();
 531                // TODO: Use the reinitialization API's once moved to .Net Standard 2.0
 532                //streamedWriterPool.Return((XmlDictionaryWriter)xmlWriter);
 825533            }
 534
 535            private TextBufferedMessageWriter TakeBufferedWriter()
 536            {
 666537                if (_bufferedWriterPool == null)
 538                {
 430539                    lock (ThisLock)
 540                    {
 430541                        if (_bufferedWriterPool == null)
 542                        {
 429543                            _bufferedWriterPool = new SynchronizedPool<TextBufferedMessageWriter>(MaxWritePoolSize);
 544                        }
 430545                    }
 546                }
 547
 666548                TextBufferedMessageWriter messageWriter = _bufferedWriterPool.Take();
 666549                if (messageWriter == null)
 550                {
 431551                    messageWriter = new TextBufferedMessageWriter(this);
 552                }
 666553                return messageWriter;
 554            }
 555
 556            private void ReturnMessageWriter(TextBufferedMessageWriter messageWriter)
 557            {
 666558                _bufferedWriterPool.Return(messageWriter);
 666559            }
 560
 561            private XmlReader TakeStreamedReader(Stream stream, Encoding enc)
 562            {
 2539563                if (_streamedReaderPool == null)
 564                {
 144565                    lock (ThisLock)
 566                    {
 144567                        if (_streamedReaderPool == null)
 568                        {
 144569                            _streamedReaderPool = new SynchronizedPool<XmlDictionaryReader>(MaxReadPoolSize);
 570                        }
 144571                    }
 572                }
 2539573                XmlDictionaryReader xmlReader = _streamedReaderPool.Take();
 2539574                if (xmlReader == null)
 575                {
 2539576                    xmlReader = XmlDictionaryReader.CreateTextReader(stream, enc, ReaderQuotas, null);
 577                }
 578                else
 579                {
 0580                    ((IXmlTextReaderInitializer)xmlReader).SetInput(stream, enc, ReaderQuotas, _onStreamedReaderClose);
 581                }
 2537582                return xmlReader;
 583            }
 584
 585            private void ReturnStreamedReader(XmlDictionaryReader xmlReader)
 586            {
 0587                _streamedReaderPool.Return(xmlReader);
 0588            }
 589
 590            private XmlDictionaryWriter CreateWriter(Stream stream)
 591            {
 0592                return XmlDictionaryWriter.CreateTextWriter(stream, _writeEncoding, false);
 593            }
 594
 595            private UTF8BufferedMessageData TakeBufferedReader()
 596            {
 773597                if (_bufferedReaderPool == null)
 598                {
 437599                    lock (ThisLock)
 600                    {
 437601                        if (_bufferedReaderPool == null)
 602                        {
 437603                            _bufferedReaderPool = new SynchronizedPool<UTF8BufferedMessageData>(MaxReadPoolSize);
 604                        }
 437605                    }
 606                }
 773607                UTF8BufferedMessageData messageData = _bufferedReaderPool.Take();
 773608                if (messageData == null)
 609                {
 531610                    messageData = new UTF8BufferedMessageData(this, maxPooledXmlReadersPerMessage);
 611                }
 773612                return messageData;
 613            }
 614
 615            private void ReturnBufferedData(UTF8BufferedMessageData messageData)
 616            {
 506617                _bufferedReaderPool.Return(messageData);
 506618            }
 619
 620            private SynchronizedPool<RecycledMessageState> RecycledStatePool
 621            {
 622                get
 623                {
 531624                    if (_recycledStatePool == null)
 625                    {
 437626                        lock (ThisLock)
 627                        {
 437628                            if (_recycledStatePool == null)
 629                            {
 437630                                _recycledStatePool = new SynchronizedPool<RecycledMessageState>(MaxReadPoolSize);
 631                            }
 437632                        }
 633                    }
 531634                    return _recycledStatePool;
 635                }
 636            }
 637
 638            private class UTF8BufferedMessageData : BufferedMessageData
 639            {
 640                private readonly TextMessageEncoder _messageEncoder;
 641                private readonly Pool<XmlDictionaryReader> _readerPool;
 642                private readonly OnXmlDictionaryReaderClose _onClose;
 643                private Encoding _encoding;
 644                private const int additionalNodeSpace = 1024;
 645
 646                public UTF8BufferedMessageData(TextMessageEncoder messageEncoder, int maxReaderPoolSize)
 531647                    : base(messageEncoder.RecycledStatePool)
 648                {
 531649                    _messageEncoder = messageEncoder;
 531650                    _readerPool = new Pool<XmlDictionaryReader>(maxReaderPoolSize);
 531651                    _onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed);
 531652                }
 653
 654                internal Encoding Encoding
 655                {
 656                    set
 657                    {
 773658                        _encoding = value;
 773659                    }
 660                }
 661
 662                public override MessageEncoder MessageEncoder
 663                {
 951664                    get { return _messageEncoder; }
 665                }
 666
 667                public override XmlDictionaryReaderQuotas Quotas
 668                {
 2146669                    get { return _messageEncoder._bufferedReadReaderQuotas; }
 670                }
 671
 672                protected override void OnClosed()
 673                {
 506674                    _messageEncoder.ReturnBufferedData(this);
 506675                }
 676
 677                protected override XmlDictionaryReader TakeXmlReader()
 678                {
 2146679                    ArraySegment<byte> buffer = Buffer;
 680
 2146681                    XmlDictionaryReader xmlReader = _readerPool.Take();
 2146682                    if (xmlReader == null)
 683                    {
 684                        // TODO: Use the reinitialization API's once moved to .Net Standard 2.0
 955685                        xmlReader = XmlDictionaryReader.CreateTextReader(buffer.Array, buffer.Offset, buffer.Count, _enc
 686                    }
 687                    else
 688                    {
 1191689                        ((IXmlTextReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, _enco
 690                    }
 691
 2146692                    return xmlReader;
 693                }
 694
 695                protected override void ReturnXmlReader(XmlDictionaryReader xmlReader)
 696                {
 1857697                    if (xmlReader != null)
 698                    {
 1857699                        _readerPool.Return(xmlReader);
 700                    }
 1857701                }
 702            }
 703
 704            private class TextBufferedMessageWriter : BufferedMessageWriter
 705            {
 706                private readonly TextMessageEncoder _messageEncoder;
 707                //XmlDictionaryWriter writer;
 708
 431709                public TextBufferedMessageWriter(TextMessageEncoder messageEncoder)
 710                {
 431711                    _messageEncoder = messageEncoder;
 431712                }
 713
 714                protected override void OnWriteStartMessage(XmlDictionaryWriter writer)
 715                {
 666716                    if (!_messageEncoder._optimizeWriteForUTF8)
 717                    {
 0718                        writer.WriteStartDocument();
 719                    }
 666720                }
 721
 722                protected override void OnWriteEndMessage(XmlDictionaryWriter writer)
 723                {
 666724                    if (!_messageEncoder._optimizeWriteForUTF8)
 725                    {
 0726                        writer.WriteEndDocument();
 727                    }
 666728                }
 729
 730                protected override XmlDictionaryWriter TakeXmlWriter(Stream stream)
 731                {
 666732                    if (_messageEncoder._optimizeWriteForUTF8)
 733                    {
 734                        //XmlDictionaryWriter returnedWriter = writer;
 735                        //if (returnedWriter == null)
 736                        //{
 737                        //    returnedWriter = XmlDictionaryWriter.CreateTextWriter(stream, messageEncoder.writeEncoding
 738                        //}
 739                        //else
 740                        //{
 741                        //    writer = null;
 742                        //    ((IXmlTextWriterInitializer)returnedWriter).SetOutput(stream, messageEncoder.writeEncoding
 743                        //}
 744                        //return returnedWriter;
 745                        // TODO: Use IXmlTextWriterInitializer when moved to .Net Standard 2.0
 666746                        return XmlDictionaryWriter.CreateTextWriter(stream, _messageEncoder._writeEncoding, false);
 747                    }
 748                    else
 749                    {
 0750                        return _messageEncoder.CreateWriter(stream);
 751                    }
 752                }
 753
 754                protected override void ReturnXmlWriter(XmlDictionaryWriter writer)
 755                {
 756                    Contract.Assert(writer != null, "writer MUST NOT be null");
 666757                    writer.Flush();
 666758                    writer.Dispose();
 759
 760                    // TODO: Use IXmlTextWriterInitializer reuse once moved to .Net Standard 2.0
 761                    //if (messageEncoder.optimizeWriteForUTF8)
 762                    //{
 763                    //    if (this.writer == null)
 764                    //        this.writer = writer;
 765                    //}
 666766                }
 767            }
 768        }
 769    }
 770
 771    internal class ContentEncoding
 772    {
 773        public string contentType;
 774        public Encoding encoding;
 775    }
 776}

Methods/Properties

.cctor()
.ctor(CoreWCF.Channels.MessageVersion,System.Text.Encoding,System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas)
Encoder()
MessageVersion()
MaxWritePoolSize()
MaxReadPoolSize()
GetSupportedEncodings()
ReaderQuotas()
GetMediaType(CoreWCF.Channels.MessageVersion)
GetContentType(System.String,System.Text.Encoding)
GetContentEncodingMap(CoreWCF.Channels.MessageVersion)
GetEncodingFromContentType(System.String,CoreWCF.Channels.ContentEncoding[])
TryGetEncodingFromCharSet(System.String,System.Text.Encoding&)
.ctor(CoreWCF.Channels.MessageVersion,System.Text.Encoding,System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas)
IsUTF8Encoding(System.Text.Encoding)
ContentType()
MaxWritePoolSize()
MaxReadPoolSize()
ReaderQuotas()
MediaType()
MessageVersion()
ThisLock()
IsCharSetSupported(System.String)
IsContentTypeSupported(System.String)
ReadMessage(System.ArraySegment`1<System.Byte>,CoreWCF.Channels.BufferManager,System.String)
ReadMessageAsync(System.IO.Stream,System.Int32,System.String)
WriteMessage(CoreWCF.Channels.Message,System.Int32,CoreWCF.Channels.BufferManager,System.Int32)
WriteMessageAsync()
TakeStreamedWriter(System.IO.Stream)
ReturnStreamedWriter(System.Xml.XmlWriter)
TakeBufferedWriter()
ReturnMessageWriter(CoreWCF.Channels.TextMessageEncoderFactory/TextMessageEncoder/TextBufferedMessageWriter)
TakeStreamedReader(System.IO.Stream,System.Text.Encoding)
ReturnStreamedReader(System.Xml.XmlDictionaryReader)
CreateWriter(System.IO.Stream)
TakeBufferedReader()
ReturnBufferedData(CoreWCF.Channels.TextMessageEncoderFactory/TextMessageEncoder/UTF8BufferedMessageData)
RecycledStatePool()
.ctor(CoreWCF.Channels.TextMessageEncoderFactory/TextMessageEncoder,System.Int32)
Encoding(System.Text.Encoding)
MessageEncoder()
Quotas()
OnClosed()
TakeXmlReader()
ReturnXmlReader(System.Xml.XmlDictionaryReader)
.ctor(CoreWCF.Channels.TextMessageEncoderFactory/TextMessageEncoder)
OnWriteStartMessage(System.Xml.XmlDictionaryWriter)
OnWriteEndMessage(System.Xml.XmlDictionaryWriter)
TakeXmlWriter(System.IO.Stream)
ReturnXmlWriter(System.Xml.XmlDictionaryWriter)