| | | 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 | | |
| | | 4 | | using System; |
| | | 5 | | using System.IO; |
| | | 6 | | using System.Runtime.Serialization.Json; |
| | | 7 | | using System.Text; |
| | | 8 | | using System.Threading.Tasks; |
| | | 9 | | using System.Xml; |
| | | 10 | | using CoreWCF.Runtime; |
| | | 11 | | using Microsoft.Extensions.ObjectPool; |
| | | 12 | | |
| | | 13 | | namespace CoreWCF.Channels |
| | | 14 | | { |
| | | 15 | | internal class JsonMessageEncoderFactory : MessageEncoderFactory |
| | | 16 | | { |
| | 1 | 17 | | private static readonly ContentEncoding[] s_applicationJsonContentEncoding = GetContentEncodingMap(JsonGlobals.A |
| | | 18 | | private readonly JsonMessageEncoder _messageEncoder; |
| | | 19 | | |
| | 29 | 20 | | public JsonMessageEncoderFactory(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionar |
| | | 21 | | { |
| | 29 | 22 | | _messageEncoder = new JsonMessageEncoder(writeEncoding, maxReadPoolSize, maxWritePoolSize, quotas, crossDoma |
| | 29 | 23 | | } |
| | | 24 | | |
| | 29 | 25 | | public override MessageEncoder Encoder => _messageEncoder; |
| | | 26 | | |
| | 0 | 27 | | public override MessageVersion MessageVersion => _messageEncoder.MessageVersion; |
| | | 28 | | |
| | | 29 | | internal static string GetContentType(WebMessageEncodingBindingElement encodingElement) |
| | | 30 | | { |
| | 0 | 31 | | if (encodingElement == null) |
| | | 32 | | { |
| | 0 | 33 | | return WebMessageEncoderFactory.GetContentType(JsonGlobals.ApplicationJsonMediaType, TextEncoderDefaults |
| | | 34 | | } |
| | | 35 | | else |
| | | 36 | | { |
| | 0 | 37 | | return WebMessageEncoderFactory.GetContentType(JsonGlobals.ApplicationJsonMediaType, encodingElement.Wri |
| | | 38 | | } |
| | | 39 | | } |
| | | 40 | | |
| | | 41 | | private static ContentEncoding[] GetContentEncodingMap(string mediaType) |
| | | 42 | | { |
| | 1 | 43 | | Encoding[] readEncodings = ContentTypeHelpers.GetSupportedEncodings(); |
| | 1 | 44 | | ContentEncoding[] map = new ContentEncoding[readEncodings.Length]; |
| | 8 | 45 | | for (int i = 0; i < readEncodings.Length; i++) |
| | | 46 | | { |
| | 3 | 47 | | ContentEncoding contentEncoding = new ContentEncoding(); |
| | 3 | 48 | | contentEncoding.contentType = WebMessageEncoderFactory.GetContentType(mediaType, readEncodings[i]); |
| | 3 | 49 | | contentEncoding.encoding = readEncodings[i]; |
| | 3 | 50 | | map[i] = contentEncoding; |
| | | 51 | | } |
| | | 52 | | |
| | 1 | 53 | | return map; |
| | | 54 | | } |
| | | 55 | | |
| | | 56 | | internal class JsonMessageEncoder : MessageEncoder |
| | | 57 | | { |
| | | 58 | | private const int MaxPooledXmlReadersPerMessage = 2; |
| | | 59 | | |
| | | 60 | | // Double-checked locking pattern requires volatile for read/write synchronization |
| | | 61 | | private volatile SynchronizedPool<JsonBufferedMessageData> _bufferedReaderPool; |
| | | 62 | | private volatile SynchronizedPool<JsonBufferedMessageWriter> _bufferedWriterPool; |
| | | 63 | | private readonly int _maxReadPoolSize; |
| | | 64 | | private readonly int _maxWritePoolSize; |
| | | 65 | | private readonly OnXmlDictionaryReaderClose _onStreamedReaderClose; |
| | | 66 | | private readonly XmlDictionaryReaderQuotas _readerQuotas; |
| | | 67 | | private readonly XmlDictionaryReaderQuotas _bufferedReadReaderQuotas; |
| | | 68 | | |
| | | 69 | | // Double-checked locking pattern requires volatile for read/write synchronization |
| | | 70 | | private volatile SynchronizedPool<RecycledMessageState> _recycledStatePool; |
| | | 71 | | private volatile SynchronizedPool<XmlDictionaryReader> _streamedReaderPool; |
| | | 72 | | private volatile SynchronizedPool<XmlDictionaryWriter> _streamedWriterPool; |
| | | 73 | | private readonly Encoding _writeEncoding; |
| | | 74 | | |
| | 29 | 75 | | public JsonMessageEncoder(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryRe |
| | | 76 | | { |
| | 29 | 77 | | if (writeEncoding == null) |
| | | 78 | | { |
| | 0 | 79 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding)); |
| | | 80 | | } |
| | | 81 | | |
| | 29 | 82 | | ThisLock = new object(); |
| | | 83 | | |
| | 29 | 84 | | TextEncoderDefaults.ValidateEncoding(writeEncoding); |
| | 29 | 85 | | _writeEncoding = writeEncoding; |
| | | 86 | | |
| | 29 | 87 | | _maxReadPoolSize = maxReadPoolSize; |
| | 29 | 88 | | _maxWritePoolSize = maxWritePoolSize; |
| | | 89 | | |
| | 29 | 90 | | _readerQuotas = new XmlDictionaryReaderQuotas(); |
| | 29 | 91 | | _onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader); |
| | 29 | 92 | | quotas.CopyTo(_readerQuotas); |
| | | 93 | | |
| | 29 | 94 | | _bufferedReadReaderQuotas = EncoderHelpers.GetBufferedReadQuotas(_readerQuotas); |
| | | 95 | | |
| | 29 | 96 | | ContentType = WebMessageEncoderFactory.GetContentType(JsonGlobals.ApplicationJsonMediaType, writeEncodin |
| | 29 | 97 | | } |
| | | 98 | | |
| | 0 | 99 | | public override string ContentType { get; } |
| | | 100 | | |
| | 0 | 101 | | public override string MediaType => JsonGlobals.ApplicationJsonMediaType; |
| | | 102 | | |
| | 30 | 103 | | public override MessageVersion MessageVersion => MessageVersion.None; |
| | | 104 | | |
| | | 105 | | private SynchronizedPool<RecycledMessageState> RecycledStatePool |
| | | 106 | | { |
| | | 107 | | get |
| | | 108 | | { |
| | 6 | 109 | | if (_recycledStatePool == null) |
| | | 110 | | { |
| | 6 | 111 | | lock (ThisLock) |
| | | 112 | | { |
| | 6 | 113 | | if (_recycledStatePool == null) |
| | | 114 | | { |
| | 6 | 115 | | _recycledStatePool = new SynchronizedPool<RecycledMessageState>(_maxReadPoolSize); |
| | | 116 | | } |
| | 6 | 117 | | } |
| | | 118 | | } |
| | | 119 | | |
| | 6 | 120 | | return _recycledStatePool; |
| | | 121 | | } |
| | | 122 | | } |
| | | 123 | | |
| | 36 | 124 | | private object ThisLock { get; } |
| | | 125 | | |
| | | 126 | | public override bool IsContentTypeSupported(string contentType) |
| | | 127 | | { |
| | 9 | 128 | | if (contentType == null) |
| | | 129 | | { |
| | 0 | 130 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(contentType)); |
| | | 131 | | } |
| | | 132 | | |
| | 9 | 133 | | return IsJsonContentType(contentType); |
| | | 134 | | } |
| | | 135 | | |
| | | 136 | | public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentTy |
| | | 137 | | { |
| | 6 | 138 | | if (bufferManager == null) |
| | | 139 | | { |
| | 0 | 140 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bufferMan |
| | | 141 | | } |
| | | 142 | | |
| | | 143 | | //if (WebTD.JsonMessageDecodingStartIsEnabled()) |
| | | 144 | | //{ |
| | | 145 | | // WebTD.JsonMessageDecodingStart(); |
| | | 146 | | //} |
| | | 147 | | |
| | | 148 | | Message message; |
| | | 149 | | |
| | 6 | 150 | | JsonBufferedMessageData messageData = TakeBufferedReader(); |
| | 6 | 151 | | messageData.Encoding = ContentTypeHelpers.GetEncodingFromContentType(contentType, JsonMessageEncoderFact |
| | 6 | 152 | | messageData.Open(buffer, bufferManager); |
| | 6 | 153 | | RecycledMessageState messageState = messageData.TakeMessageState(); |
| | 6 | 154 | | if (messageState == null) |
| | | 155 | | { |
| | 6 | 156 | | messageState = new RecycledMessageState(); |
| | | 157 | | } |
| | 6 | 158 | | message = new BufferedMessage(messageData, messageState); |
| | | 159 | | |
| | 6 | 160 | | message.Properties.Encoder = this; |
| | | 161 | | |
| | | 162 | | //if (SMTD.MessageReadByEncoderIsEnabled() && buffer != null) |
| | | 163 | | //{ |
| | | 164 | | // SMTD.MessageReadByEncoder( |
| | | 165 | | // EventTraceActivityHelper.TryExtractActivity(message, true), |
| | | 166 | | // buffer.Count, |
| | | 167 | | // this); |
| | | 168 | | //} |
| | | 169 | | |
| | | 170 | | //if (MessageLogger.LogMessagesAtTransportLevel) |
| | | 171 | | //{ |
| | | 172 | | // MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive); |
| | | 173 | | //} |
| | | 174 | | |
| | 6 | 175 | | return message; |
| | | 176 | | } |
| | | 177 | | |
| | | 178 | | public override Task<Message> ReadMessageAsync(Stream stream, int maxSizeOfHeaders, string contentType) |
| | | 179 | | { |
| | 0 | 180 | | if (stream == null) |
| | | 181 | | { |
| | 0 | 182 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream))) |
| | | 183 | | } |
| | | 184 | | |
| | | 185 | | //if (WebTD.JsonMessageDecodingStartIsEnabled()) |
| | | 186 | | //{ |
| | | 187 | | // WebTD.JsonMessageDecodingStart(); |
| | | 188 | | //} |
| | | 189 | | |
| | 0 | 190 | | XmlReader reader = TakeStreamedReader(stream, ContentTypeHelpers.GetEncodingFromContentType(contentType, |
| | 0 | 191 | | Message message = Message.CreateMessage(reader, maxSizeOfHeaders, MessageVersion.None); |
| | 0 | 192 | | message.Properties.Encoder = this; |
| | | 193 | | |
| | | 194 | | //if (SMTD.StreamedMessageReadByEncoderIsEnabled()) |
| | | 195 | | //{ |
| | | 196 | | // SMTD.StreamedMessageReadByEncoder(EventTraceActivityHelper.TryExtractActivity(message, true)); |
| | | 197 | | //} |
| | | 198 | | |
| | | 199 | | //if (MessageLogger.LogMessagesAtTransportLevel) |
| | | 200 | | //{ |
| | | 201 | | // MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive); |
| | | 202 | | //} |
| | | 203 | | |
| | 0 | 204 | | return Task.FromResult(message); |
| | | 205 | | } |
| | | 206 | | |
| | | 207 | | public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferMan |
| | | 208 | | { |
| | 24 | 209 | | if (message == null) |
| | | 210 | | { |
| | 0 | 211 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message)) |
| | | 212 | | } |
| | | 213 | | |
| | 24 | 214 | | if (bufferManager == null) |
| | | 215 | | { |
| | 0 | 216 | | throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(bufferManager)), message); |
| | | 217 | | } |
| | | 218 | | |
| | 24 | 219 | | if (maxMessageSize < 0) |
| | | 220 | | { |
| | 0 | 221 | | throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxMessageSize), maxMessa |
| | 0 | 222 | | SR.Format(SRCommon.ValueMustBeNonNegative)), message); |
| | | 223 | | } |
| | | 224 | | |
| | 24 | 225 | | if (messageOffset < 0 || messageOffset > maxMessageSize) |
| | | 226 | | { |
| | 0 | 227 | | throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(messageOffset), messageOf |
| | 0 | 228 | | SR.Format(SR.JsonValueMustBeInRange, 0, maxMessageSize)), message); |
| | | 229 | | } |
| | | 230 | | |
| | | 231 | | //EventTraceActivity eventTraceActivity = null; |
| | | 232 | | //if (WebTD.JsonMessageEncodingStartIsEnabled()) |
| | | 233 | | //{ |
| | | 234 | | // eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message); |
| | | 235 | | // WebTD.JsonMessageEncodingStart(eventTraceActivity); |
| | | 236 | | //} |
| | | 237 | | |
| | 24 | 238 | | ThrowIfMismatchedMessageVersion(message); |
| | 24 | 239 | | message.Properties.Encoder = this; |
| | 24 | 240 | | JsonBufferedMessageWriter messageWriter = TakeBufferedWriter(); |
| | | 241 | | |
| | 24 | 242 | | ArraySegment<byte> messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMe |
| | 24 | 243 | | ReturnMessageWriter(messageWriter); |
| | | 244 | | |
| | | 245 | | //if (SMTD.MessageWrittenByEncoderIsEnabled() && messageData != null) |
| | | 246 | | //{ |
| | | 247 | | // SMTD.MessageWrittenByEncoder( |
| | | 248 | | // eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message), |
| | | 249 | | // messageData.Count, |
| | | 250 | | // this); |
| | | 251 | | //} |
| | | 252 | | |
| | | 253 | | //if (MessageLogger.LogMessagesAtTransportLevel) |
| | | 254 | | //{ |
| | | 255 | | // XmlDictionaryReader xmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader( |
| | | 256 | | // messageData.Array, messageData.Offset, messageData.Count, null, XmlDictionaryReaderQuotas.Max, |
| | | 257 | | // MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend); |
| | | 258 | | //} |
| | | 259 | | |
| | 24 | 260 | | return messageData; |
| | | 261 | | } |
| | | 262 | | |
| | | 263 | | public override Task WriteMessageAsync(Message message, Stream stream) |
| | | 264 | | { |
| | 0 | 265 | | if (message == null) |
| | | 266 | | { |
| | 0 | 267 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message)) |
| | | 268 | | } |
| | | 269 | | |
| | 0 | 270 | | if (stream == null) |
| | | 271 | | { |
| | 0 | 272 | | throw TraceUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)), message); |
| | | 273 | | } |
| | | 274 | | |
| | 0 | 275 | | ThrowIfMismatchedMessageVersion(message); |
| | | 276 | | |
| | | 277 | | //EventTraceActivity eventTraceActivity = null; |
| | | 278 | | //if (WebTD.JsonMessageEncodingStartIsEnabled()) |
| | | 279 | | //{ |
| | | 280 | | // eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message); |
| | | 281 | | // WebTD.JsonMessageEncodingStart(eventTraceActivity); |
| | | 282 | | //} |
| | | 283 | | |
| | 0 | 284 | | message.Properties.Encoder = this; |
| | 0 | 285 | | XmlDictionaryWriter xmlWriter = TakeStreamedWriter(stream); |
| | | 286 | | |
| | 0 | 287 | | xmlWriter.WriteStartDocument(); |
| | 0 | 288 | | message.WriteMessage(xmlWriter); |
| | 0 | 289 | | xmlWriter.WriteEndDocument(); |
| | 0 | 290 | | xmlWriter.Flush(); |
| | 0 | 291 | | ReturnStreamedWriter(xmlWriter); |
| | | 292 | | |
| | | 293 | | //if (SMTD.StreamedMessageWrittenByEncoderIsEnabled()) |
| | | 294 | | //{ |
| | | 295 | | // SMTD.StreamedMessageWrittenByEncoder( |
| | | 296 | | // eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message)); |
| | | 297 | | //} |
| | | 298 | | |
| | | 299 | | //if (MessageLogger.LogMessagesAtTransportLevel) |
| | | 300 | | //{ |
| | | 301 | | // MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend); |
| | | 302 | | //} |
| | | 303 | | |
| | 0 | 304 | | return Task.CompletedTask; |
| | | 305 | | } |
| | | 306 | | |
| | 0 | 307 | | protected override bool IsCharSetSupported(string charSet) => TextEncoderDefaults.TryGetEncoding(charSet, ou |
| | | 308 | | |
| | 9 | 309 | | private bool IsJsonContentType(string contentType) => IsContentTypeSupported(contentType, JsonGlobals.Applic |
| | | 310 | | |
| | | 311 | | private void ReturnBufferedData(JsonBufferedMessageData messageData) |
| | | 312 | | { |
| | 0 | 313 | | _bufferedReaderPool.Return(messageData); |
| | 0 | 314 | | } |
| | | 315 | | |
| | | 316 | | private void ReturnMessageWriter(JsonBufferedMessageWriter messageWriter) |
| | | 317 | | { |
| | 24 | 318 | | _bufferedWriterPool.Return(messageWriter); |
| | 24 | 319 | | } |
| | | 320 | | |
| | | 321 | | private void ReturnStreamedReader(XmlDictionaryReader xmlReader) |
| | | 322 | | { |
| | 0 | 323 | | _streamedReaderPool.Return(xmlReader); |
| | 0 | 324 | | } |
| | | 325 | | |
| | | 326 | | private void ReturnStreamedWriter(XmlWriter xmlWriter) |
| | | 327 | | { |
| | 0 | 328 | | xmlWriter.Close(); |
| | 0 | 329 | | _streamedWriterPool.Return((XmlDictionaryWriter)xmlWriter); |
| | 0 | 330 | | } |
| | | 331 | | |
| | | 332 | | private JsonBufferedMessageData TakeBufferedReader() |
| | | 333 | | { |
| | 6 | 334 | | if (_bufferedReaderPool == null) |
| | | 335 | | { |
| | 6 | 336 | | lock (ThisLock) |
| | | 337 | | { |
| | 6 | 338 | | if (_bufferedReaderPool == null) |
| | | 339 | | { |
| | 6 | 340 | | _bufferedReaderPool = new SynchronizedPool<JsonBufferedMessageData>(_maxReadPoolSize); |
| | | 341 | | } |
| | 6 | 342 | | } |
| | | 343 | | } |
| | | 344 | | |
| | 6 | 345 | | JsonBufferedMessageData messageData = _bufferedReaderPool.Take(); |
| | 6 | 346 | | if (messageData == null) |
| | | 347 | | { |
| | 6 | 348 | | messageData = new JsonBufferedMessageData(this, MaxPooledXmlReadersPerMessage); |
| | | 349 | | } |
| | | 350 | | |
| | 6 | 351 | | return messageData; |
| | | 352 | | } |
| | | 353 | | |
| | | 354 | | private JsonBufferedMessageWriter TakeBufferedWriter() |
| | | 355 | | { |
| | 24 | 356 | | if (_bufferedWriterPool == null) |
| | | 357 | | { |
| | 24 | 358 | | lock (ThisLock) |
| | | 359 | | { |
| | 24 | 360 | | if (_bufferedWriterPool == null) |
| | | 361 | | { |
| | 24 | 362 | | _bufferedWriterPool = new SynchronizedPool<JsonBufferedMessageWriter>(_maxWritePoolSize); |
| | | 363 | | } |
| | 24 | 364 | | } |
| | | 365 | | } |
| | | 366 | | |
| | 24 | 367 | | JsonBufferedMessageWriter messageWriter = _bufferedWriterPool.Take(); |
| | 24 | 368 | | if (messageWriter == null) |
| | | 369 | | { |
| | 24 | 370 | | messageWriter = new JsonBufferedMessageWriter(this); |
| | | 371 | | } |
| | | 372 | | |
| | 24 | 373 | | return messageWriter; |
| | | 374 | | } |
| | | 375 | | |
| | | 376 | | private XmlDictionaryReader TakeStreamedReader(Stream stream, Encoding enc) |
| | | 377 | | { |
| | 0 | 378 | | if (_streamedReaderPool == null) |
| | | 379 | | { |
| | 0 | 380 | | lock (ThisLock) |
| | | 381 | | { |
| | 0 | 382 | | if (_streamedReaderPool == null) |
| | | 383 | | { |
| | 0 | 384 | | _streamedReaderPool = new SynchronizedPool<XmlDictionaryReader>(_maxReadPoolSize); |
| | | 385 | | } |
| | 0 | 386 | | } |
| | | 387 | | } |
| | | 388 | | |
| | 0 | 389 | | XmlDictionaryReader xmlReader = _streamedReaderPool.Take(); |
| | 0 | 390 | | if (xmlReader == null) |
| | | 391 | | { |
| | 0 | 392 | | xmlReader = JsonReaderWriterFactory.CreateJsonReader(stream, enc, _readerQuotas, _onStreamedReaderCl |
| | | 393 | | } |
| | | 394 | | else |
| | | 395 | | { |
| | 0 | 396 | | ((IXmlJsonReaderInitializer)xmlReader).SetInput(stream, enc, _readerQuotas, _onStreamedReaderClose); |
| | | 397 | | } |
| | | 398 | | |
| | 0 | 399 | | return xmlReader; |
| | | 400 | | } |
| | | 401 | | |
| | | 402 | | private XmlDictionaryWriter TakeStreamedWriter(Stream stream) |
| | | 403 | | { |
| | 0 | 404 | | if (_streamedWriterPool == null) |
| | | 405 | | { |
| | 0 | 406 | | lock (ThisLock) |
| | | 407 | | { |
| | 0 | 408 | | if (_streamedWriterPool == null) |
| | | 409 | | { |
| | 0 | 410 | | _streamedWriterPool = new SynchronizedPool<XmlDictionaryWriter>(_maxWritePoolSize); |
| | | 411 | | } |
| | 0 | 412 | | } |
| | | 413 | | } |
| | | 414 | | |
| | 0 | 415 | | XmlDictionaryWriter xmlWriter = _streamedWriterPool.Take(); |
| | 0 | 416 | | if (xmlWriter == null) |
| | | 417 | | { |
| | 0 | 418 | | xmlWriter = JsonReaderWriterFactory.CreateJsonWriter(stream, _writeEncoding, false); |
| | | 419 | | } |
| | | 420 | | else |
| | | 421 | | { |
| | 0 | 422 | | ((IXmlJsonWriterInitializer)xmlWriter).SetOutput(stream, _writeEncoding, false); |
| | | 423 | | } |
| | | 424 | | |
| | 0 | 425 | | return xmlWriter; |
| | | 426 | | } |
| | | 427 | | |
| | | 428 | | internal class JsonBufferedMessageData : BufferedMessageData |
| | | 429 | | { |
| | | 430 | | private Encoding _encoding; |
| | | 431 | | private readonly JsonMessageEncoder _messageEncoder; |
| | | 432 | | private readonly OnXmlDictionaryReaderClose _onClose; |
| | | 433 | | private readonly Pool<XmlDictionaryReader> _readerPool; |
| | | 434 | | |
| | | 435 | | public JsonBufferedMessageData(JsonMessageEncoder messageEncoder, int maxReaderPoolSize) |
| | 6 | 436 | | : base(messageEncoder.RecycledStatePool) |
| | | 437 | | { |
| | 6 | 438 | | _messageEncoder = messageEncoder; |
| | 6 | 439 | | _onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed); |
| | 6 | 440 | | _readerPool = new Pool<XmlDictionaryReader>(maxReaderPoolSize); |
| | 6 | 441 | | } |
| | | 442 | | |
| | 6 | 443 | | public override MessageEncoder MessageEncoder => _messageEncoder; |
| | | 444 | | |
| | 6 | 445 | | public override XmlDictionaryReaderQuotas Quotas => _messageEncoder._bufferedReadReaderQuotas; |
| | | 446 | | |
| | | 447 | | internal Encoding Encoding |
| | | 448 | | { |
| | | 449 | | set |
| | | 450 | | { |
| | 6 | 451 | | _encoding = value; |
| | 6 | 452 | | } |
| | | 453 | | } |
| | | 454 | | |
| | | 455 | | protected override void OnClosed() |
| | | 456 | | { |
| | 0 | 457 | | _messageEncoder.ReturnBufferedData(this); |
| | 0 | 458 | | } |
| | | 459 | | |
| | | 460 | | protected override void ReturnXmlReader(XmlDictionaryReader xmlReader) |
| | | 461 | | { |
| | 0 | 462 | | if (xmlReader != null) |
| | | 463 | | { |
| | 0 | 464 | | _readerPool.Return(xmlReader); |
| | | 465 | | } |
| | 0 | 466 | | } |
| | | 467 | | |
| | | 468 | | protected override XmlDictionaryReader TakeXmlReader() |
| | | 469 | | { |
| | 6 | 470 | | ArraySegment<byte> buffer = Buffer; |
| | | 471 | | |
| | 6 | 472 | | XmlDictionaryReader xmlReader = _readerPool.Take(); |
| | 6 | 473 | | if (xmlReader == null) |
| | | 474 | | { |
| | 6 | 475 | | xmlReader = JsonReaderWriterFactory.CreateJsonReader(buffer.Array, buffer.Offset, buffer.Count, |
| | | 476 | | } |
| | | 477 | | else |
| | | 478 | | { |
| | 0 | 479 | | ((IXmlJsonReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, _enco |
| | | 480 | | } |
| | | 481 | | |
| | 6 | 482 | | return xmlReader; |
| | | 483 | | } |
| | | 484 | | } |
| | | 485 | | |
| | | 486 | | internal class JsonBufferedMessageWriter : BufferedMessageWriter |
| | | 487 | | { |
| | | 488 | | private readonly JsonMessageEncoder _messageEncoder; |
| | | 489 | | private XmlDictionaryWriter _returnedWriter; |
| | | 490 | | |
| | 24 | 491 | | public JsonBufferedMessageWriter(JsonMessageEncoder messageEncoder) |
| | | 492 | | { |
| | 24 | 493 | | _messageEncoder = messageEncoder; |
| | 24 | 494 | | } |
| | | 495 | | |
| | | 496 | | protected override void OnWriteEndMessage(XmlDictionaryWriter writer) |
| | | 497 | | { |
| | 24 | 498 | | writer.WriteEndDocument(); |
| | 24 | 499 | | } |
| | | 500 | | |
| | | 501 | | protected override void OnWriteStartMessage(XmlDictionaryWriter writer) |
| | | 502 | | { |
| | 24 | 503 | | writer.WriteStartDocument(); |
| | 24 | 504 | | } |
| | | 505 | | |
| | | 506 | | protected override void ReturnXmlWriter(XmlDictionaryWriter writer) |
| | | 507 | | { |
| | 24 | 508 | | writer.Close(); |
| | | 509 | | |
| | 24 | 510 | | if (_returnedWriter == null) |
| | | 511 | | { |
| | 24 | 512 | | _returnedWriter = writer; |
| | | 513 | | } |
| | 24 | 514 | | } |
| | | 515 | | |
| | | 516 | | protected override XmlDictionaryWriter TakeXmlWriter(Stream stream) |
| | | 517 | | { |
| | | 518 | | XmlDictionaryWriter writer; |
| | 24 | 519 | | if (_returnedWriter == null) |
| | | 520 | | { |
| | 24 | 521 | | writer = JsonReaderWriterFactory.CreateJsonWriter(stream, _messageEncoder._writeEncoding, false) |
| | | 522 | | } |
| | | 523 | | else |
| | | 524 | | { |
| | 0 | 525 | | writer = _returnedWriter; |
| | 0 | 526 | | ((IXmlJsonWriterInitializer)writer).SetOutput(stream, _messageEncoder._writeEncoding, false); |
| | 0 | 527 | | _returnedWriter = null; |
| | | 528 | | } |
| | | 529 | | |
| | 24 | 530 | | return writer; |
| | | 531 | | } |
| | | 532 | | } |
| | | 533 | | } |
| | | 534 | | } |
| | | 535 | | } |