1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.ServiceModel.Channels
7 using System.Collections.Generic;
8 using System.Diagnostics;
9 using System.Globalization;
12 using System.Runtime.Serialization;
13 using System.ServiceModel;
14 using System.ServiceModel.Diagnostics;
15 using System.ServiceModel.Dispatcher;
16 using System.Threading;
19 public abstract class Message : IDisposable
22 SeekableMessageNavigator messageNavigator;
23 internal const int InitialBufferSize = 1024;
25 public abstract MessageHeaders Headers { get; } // must never return null
27 protected bool IsDisposed
29 get { return state == MessageState.Closed; }
32 public virtual bool IsFault
37 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
38 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
44 public virtual bool IsEmpty
49 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
50 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
56 public abstract MessageProperties Properties { get; }
58 public abstract MessageVersion Version { get; } // must never return null
60 internal virtual void SetProperty(string name, object value)
62 MessageProperties prop = Properties;
70 internal virtual bool GetProperty(string name, out object result)
72 MessageProperties prop = Properties;
76 return prop.TryGetValue(name, out result);
83 internal virtual RecycledMessageState RecycledMessageState
88 public MessageState State
93 internal void BodyToString(XmlDictionaryWriter writer)
95 OnBodyToString(writer);
100 if (state != MessageState.Closed)
102 state = MessageState.Closed;
104 if (DiagnosticUtility.ShouldTraceVerbose)
106 TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosed,
107 SR.GetString(SR.TraceCodeMessageClosed), this);
112 if (DiagnosticUtility.ShouldTraceVerbose)
114 TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosedAgain,
115 SR.GetString(SR.TraceCodeMessageClosedAgain), this);
120 public MessageBuffer CreateBufferedCopy(int maxBufferSize)
122 if (maxBufferSize < 0)
123 throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxBufferSize", maxBufferSize,
124 SR.GetString(SR.ValueMustBeNonNegative)), this);
127 case MessageState.Created:
128 state = MessageState.Copied;
129 if (DiagnosticUtility.ShouldTraceVerbose)
131 TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageCopied,
132 SR.GetString(SR.TraceCodeMessageCopied), this, this);
135 case MessageState.Closed:
136 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
137 case MessageState.Copied:
138 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
139 case MessageState.Read:
140 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
141 case MessageState.Written:
142 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
144 Fx.Assert(SR.GetString(SR.InvalidMessageState));
145 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
147 return OnCreateBufferedCopy(maxBufferSize);
150 static Type GetObjectType(object value)
152 return (value == null) ? typeof(object) : value.GetType();
155 static public Message CreateMessage(MessageVersion version, string action, object body)
157 return CreateMessage(version, action, body, DataContractSerializerDefaults.CreateSerializer(GetObjectType(body), int.MaxValue/*maxItems*/));
160 static public Message CreateMessage(MessageVersion version, string action, object body, XmlObjectSerializer serializer)
163 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
164 if (serializer == null)
165 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
166 return new BodyWriterMessage(version, action, new XmlObjectSerializerBodyWriter(body, serializer));
169 static public Message CreateMessage(MessageVersion version, string action, XmlReader body)
171 return CreateMessage(version, action, XmlDictionaryReader.CreateDictionaryReader(body));
174 static public Message CreateMessage(MessageVersion version, string action, XmlDictionaryReader body)
177 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("body");
179 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version");
181 return CreateMessage(version, action, new XmlReaderBodyWriter(body, version.Envelope));
184 static public Message CreateMessage(MessageVersion version, string action, BodyWriter body)
187 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
189 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("body"));
190 return new BodyWriterMessage(version, action, body);
193 static internal Message CreateMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter body)
196 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
198 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("body"));
199 return new BodyWriterMessage(version, actionHeader, body);
202 static public Message CreateMessage(MessageVersion version, string action)
205 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
206 return new BodyWriterMessage(version, action, EmptyBodyWriter.Value);
209 static internal Message CreateMessage(MessageVersion version, ActionHeader actionHeader)
212 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
213 return new BodyWriterMessage(version, actionHeader, EmptyBodyWriter.Value);
216 static public Message CreateMessage(XmlReader envelopeReader, int maxSizeOfHeaders, MessageVersion version)
218 return CreateMessage(XmlDictionaryReader.CreateDictionaryReader(envelopeReader), maxSizeOfHeaders, version);
221 static public Message CreateMessage(XmlDictionaryReader envelopeReader, int maxSizeOfHeaders, MessageVersion version)
223 if (envelopeReader == null)
224 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("envelopeReader"));
226 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
227 Message message = new StreamedMessage(envelopeReader, maxSizeOfHeaders, version);
231 static public Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, string action)
234 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
235 if (faultCode == null)
236 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faultCode"));
238 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason"));
240 return CreateMessage(version, MessageFault.CreateFault(faultCode, reason), action);
243 static public Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, object detail, string action)
246 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
247 if (faultCode == null)
248 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faultCode"));
250 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason"));
252 return CreateMessage(version, MessageFault.CreateFault(faultCode, new FaultReason(reason), detail), action);
255 static public Message CreateMessage(MessageVersion version, MessageFault fault, string action)
258 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("fault"));
260 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
261 return new BodyWriterMessage(version, action, new FaultBodyWriter(fault, version.Envelope));
264 internal Exception CreateMessageDisposedException()
266 return new ObjectDisposedException("", SR.GetString(SR.MessageClosed));
269 void IDisposable.Dispose()
274 public T GetBody<T>()
276 XmlDictionaryReader reader = GetReaderAtBodyContents(); // This call will change the message state to Read.
277 return OnGetBody<T>(reader);
280 protected virtual T OnGetBody<T>(XmlDictionaryReader reader)
282 return this.GetBodyCore<T>(reader, DataContractSerializerDefaults.CreateSerializer(typeof(T), int.MaxValue/*maxItems*/));
285 public T GetBody<T>(XmlObjectSerializer serializer)
287 if (serializer == null)
288 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
289 return this.GetBodyCore<T>(GetReaderAtBodyContents(), serializer);
292 T GetBodyCore<T>(XmlDictionaryReader reader, XmlObjectSerializer serializer)
297 value = (T)serializer.ReadObject(reader);
298 this.ReadFromBodyContentsToEnd(reader);
303 internal virtual XmlDictionaryReader GetReaderAtHeader()
305 XmlBuffer buffer = new XmlBuffer(int.MaxValue);
306 XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
307 WriteStartEnvelope(writer);
308 MessageHeaders headers = this.Headers;
309 for (int i = 0; i < headers.Count; i++)
310 headers.WriteHeader(i, writer);
311 writer.WriteEndElement();
312 writer.WriteEndElement();
313 buffer.CloseSection();
315 XmlDictionaryReader reader = buffer.GetReader(0);
316 reader.ReadStartElement();
317 reader.MoveToStartElement();
321 public XmlDictionaryReader GetReaderAtBodyContents()
323 EnsureReadMessageState();
325 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageIsEmpty)), this);
326 return OnGetReaderAtBodyContents();
329 internal void EnsureReadMessageState()
333 case MessageState.Created:
334 state = MessageState.Read;
335 if (DiagnosticUtility.ShouldTraceVerbose)
337 TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageRead, SR.GetString(SR.TraceCodeMessageRead), this);
340 case MessageState.Copied:
341 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
342 case MessageState.Read:
343 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
344 case MessageState.Written:
345 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
346 case MessageState.Closed:
347 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
349 Fx.Assert(SR.GetString(SR.InvalidMessageState));
350 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
354 internal SeekableMessageNavigator GetNavigator(bool navigateBody, int maxNodes)
357 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
358 if (null == this.messageNavigator)
360 this.messageNavigator = new SeekableMessageNavigator(this, maxNodes, XmlSpace.Default, navigateBody, false);
364 this.messageNavigator.ForkNodeCount(maxNodes);
367 return this.messageNavigator;
370 internal void InitializeReply(Message request)
372 UniqueId requestMessageID = request.Headers.MessageId;
373 if (requestMessageID == null)
374 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.RequestMessageDoesNotHaveAMessageID)), request);
375 Headers.RelatesTo = requestMessageID;
378 static internal bool IsFaultStartElement(XmlDictionaryReader reader, EnvelopeVersion version)
380 return reader.IsStartElement(XD.MessageDictionary.Fault, version.DictionaryNamespace);
383 protected virtual void OnBodyToString(XmlDictionaryWriter writer)
385 writer.WriteString(SR.GetString(SR.MessageBodyIsUnknown));
388 protected virtual MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
390 return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max);
393 internal MessageBuffer OnCreateBufferedCopy(int maxBufferSize, XmlDictionaryReaderQuotas quotas)
395 XmlBuffer msgBuffer = new XmlBuffer(maxBufferSize);
396 XmlDictionaryWriter writer = msgBuffer.OpenSection(quotas);
397 OnWriteMessage(writer);
398 msgBuffer.CloseSection();
400 return new DefaultMessageBuffer(this, msgBuffer);
403 protected virtual void OnClose()
407 protected virtual XmlDictionaryReader OnGetReaderAtBodyContents()
409 XmlBuffer bodyBuffer = new XmlBuffer(int.MaxValue);
410 XmlDictionaryWriter writer = bodyBuffer.OpenSection(XmlDictionaryReaderQuotas.Max);
411 if (this.Version.Envelope != EnvelopeVersion.None)
413 OnWriteStartEnvelope(writer);
414 OnWriteStartBody(writer);
416 OnWriteBodyContents(writer);
417 if (this.Version.Envelope != EnvelopeVersion.None)
419 writer.WriteEndElement();
420 writer.WriteEndElement();
422 bodyBuffer.CloseSection();
424 XmlDictionaryReader reader = bodyBuffer.GetReader(0);
425 if (this.Version.Envelope != EnvelopeVersion.None)
427 reader.ReadStartElement();
428 reader.ReadStartElement();
430 reader.MoveToContent();
434 protected virtual void OnWriteStartBody(XmlDictionaryWriter writer)
436 MessageDictionary messageDictionary = XD.MessageDictionary;
437 writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Body, Version.Envelope.DictionaryNamespace);
440 public void WriteBodyContents(XmlDictionaryWriter writer)
442 EnsureWriteMessageState(writer);
443 OnWriteBodyContents(writer);
446 public IAsyncResult BeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
448 EnsureWriteMessageState(writer);
449 return this.OnBeginWriteBodyContents(writer, callback, state);
452 public void EndWriteBodyContents(IAsyncResult result)
454 this.OnEndWriteBodyContents(result);
457 protected abstract void OnWriteBodyContents(XmlDictionaryWriter writer);
459 protected virtual IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
461 return new OnWriteBodyContentsAsyncResult(writer, this, callback, state);
464 protected virtual void OnEndWriteBodyContents(IAsyncResult result)
466 OnWriteBodyContentsAsyncResult.End(result);
469 public void WriteStartEnvelope(XmlDictionaryWriter writer)
472 throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this);
474 OnWriteStartEnvelope(writer);
477 protected virtual void OnWriteStartEnvelope(XmlDictionaryWriter writer)
479 EnvelopeVersion envelopeVersion = Version.Envelope;
480 if (envelopeVersion != EnvelopeVersion.None)
482 MessageDictionary messageDictionary = XD.MessageDictionary;
483 writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Envelope, envelopeVersion.DictionaryNamespace);
484 WriteSharedHeaderPrefixes(writer);
488 protected virtual void OnWriteStartHeaders(XmlDictionaryWriter writer)
490 EnvelopeVersion envelopeVersion = Version.Envelope;
491 if (envelopeVersion != EnvelopeVersion.None)
493 MessageDictionary messageDictionary = XD.MessageDictionary;
494 writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Header, envelopeVersion.DictionaryNamespace);
498 public override string ToString()
502 return base.ToString();
505 StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
506 EncodingFallbackAwareXmlTextWriter textWriter = new EncodingFallbackAwareXmlTextWriter(stringWriter);
507 textWriter.Formatting = Formatting.Indented;
508 XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(textWriter);
513 return stringWriter.ToString();
515 catch (XmlException e)
517 return SR.GetString(SR.MessageBodyToStringError, e.GetType().ToString(), e.Message);
521 internal void ToString(XmlDictionaryWriter writer)
525 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
528 if (this.Version.Envelope != EnvelopeVersion.None)
530 WriteStartEnvelope(writer);
531 WriteStartHeaders(writer);
532 MessageHeaders headers = this.Headers;
533 for (int i = 0; i < headers.Count; i++)
535 headers.WriteHeader(i, writer);
538 writer.WriteEndElement();
539 MessageDictionary messageDictionary = XD.MessageDictionary;
540 WriteStartBody(writer);
543 BodyToString(writer);
545 if (this.Version.Envelope != EnvelopeVersion.None)
547 writer.WriteEndElement();
548 writer.WriteEndElement();
552 public string GetBodyAttribute(string localName, string ns)
554 if (localName == null)
555 throw TraceUtility.ThrowHelperError(new ArgumentNullException("localName"), this);
557 throw TraceUtility.ThrowHelperError(new ArgumentNullException("ns"), this);
560 case MessageState.Created:
562 case MessageState.Copied:
563 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
564 case MessageState.Read:
565 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
566 case MessageState.Written:
567 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
568 case MessageState.Closed:
569 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
571 Fx.Assert(SR.GetString(SR.InvalidMessageState));
572 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
574 return OnGetBodyAttribute(localName, ns);
577 protected virtual string OnGetBodyAttribute(string localName, string ns)
582 internal void ReadFromBodyContentsToEnd(XmlDictionaryReader reader)
584 Message.ReadFromBodyContentsToEnd(reader, this.Version.Envelope);
587 static void ReadFromBodyContentsToEnd(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
589 if (envelopeVersion != EnvelopeVersion.None)
591 reader.ReadEndElement(); // </Body>
592 reader.ReadEndElement(); // </Envelope>
594 reader.MoveToContent();
597 internal static bool ReadStartBody(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion, out bool isFault, out bool isEmpty)
599 if (reader.IsEmptyElement)
604 reader.ReadEndElement();
610 if (reader.NodeType != XmlNodeType.Element)
611 reader.MoveToContent();
612 if (reader.NodeType == XmlNodeType.Element)
614 isFault = IsFaultStartElement(reader, envelopeVersion);
617 else if (reader.NodeType == XmlNodeType.EndElement)
621 Message.ReadFromBodyContentsToEnd(reader, envelopeVersion);
634 public void WriteBody(XmlWriter writer)
636 WriteBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
639 public void WriteBody(XmlDictionaryWriter writer)
641 WriteStartBody(writer);
642 WriteBodyContents(writer);
643 writer.WriteEndElement();
646 public void WriteStartBody(XmlWriter writer)
648 WriteStartBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
651 public void WriteStartBody(XmlDictionaryWriter writer)
654 throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this);
655 OnWriteStartBody(writer);
658 internal void WriteStartHeaders(XmlDictionaryWriter writer)
660 OnWriteStartHeaders(writer);
663 public void WriteMessage(XmlWriter writer)
665 WriteMessage(XmlDictionaryWriter.CreateDictionaryWriter(writer));
668 public void WriteMessage(XmlDictionaryWriter writer)
670 EnsureWriteMessageState(writer);
671 OnWriteMessage(writer);
674 void EnsureWriteMessageState(XmlDictionaryWriter writer)
677 throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this);
680 case MessageState.Created:
681 state = MessageState.Written;
682 if (DiagnosticUtility.ShouldTraceVerbose)
684 TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageWritten, SR.GetString(SR.TraceCodeMessageWritten), this);
687 case MessageState.Copied:
688 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
689 case MessageState.Read:
690 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
691 case MessageState.Written:
692 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
693 case MessageState.Closed:
694 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
696 Fx.Assert(SR.GetString(SR.InvalidMessageState));
697 throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
701 public IAsyncResult BeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
703 EnsureWriteMessageState(writer);
704 return OnBeginWriteMessage(writer, callback, state);
707 public void EndWriteMessage(IAsyncResult result)
709 OnEndWriteMessage(result);
712 protected virtual void OnWriteMessage(XmlDictionaryWriter writer)
714 WriteMessagePreamble(writer);
715 OnWriteBodyContents(writer);
716 WriteMessagePostamble(writer);
719 internal void WriteMessagePreamble(XmlDictionaryWriter writer)
721 if (this.Version.Envelope != EnvelopeVersion.None)
723 OnWriteStartEnvelope(writer);
725 MessageHeaders headers = this.Headers;
726 int headersCount = headers.Count;
727 if (headersCount > 0)
729 OnWriteStartHeaders(writer);
730 for (int i = 0; i < headersCount; i++)
732 headers.WriteHeader(i, writer);
734 writer.WriteEndElement();
737 OnWriteStartBody(writer);
741 internal void WriteMessagePostamble(XmlDictionaryWriter writer)
743 if (this.Version.Envelope != EnvelopeVersion.None)
745 writer.WriteEndElement();
746 writer.WriteEndElement();
750 protected virtual IAsyncResult OnBeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
752 return new OnWriteMessageAsyncResult(writer, this, callback, state);
755 protected virtual void OnEndWriteMessage(IAsyncResult result)
757 OnWriteMessageAsyncResult.End(result);
760 void WriteSharedHeaderPrefixes(XmlDictionaryWriter writer)
762 MessageHeaders headers = Headers;
763 int count = headers.Count;
764 int prefixesWritten = 0;
765 for (int i = 0; i < count; i++)
767 if (this.Version.Addressing == AddressingVersion.None && headers[i].Namespace == AddressingVersion.None.Namespace)
772 IMessageHeaderWithSharedNamespace headerWithSharedNamespace = headers[i] as IMessageHeaderWithSharedNamespace;
773 if (headerWithSharedNamespace != null)
775 XmlDictionaryString prefix = headerWithSharedNamespace.SharedPrefix;
776 string prefixString = prefix.Value;
777 if (!((prefixString.Length == 1)))
779 Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixString.Length == 1) -- IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.");
780 throw TraceUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.")), this);
783 int prefixIndex = prefixString[0] - 'a';
784 if (!((prefixIndex >= 0 && prefixIndex < 26)))
786 Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixIndex >= 0 && prefixIndex < 26) -- IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.");
787 throw TraceUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.")), this);
789 int prefixBit = 1 << prefixIndex;
790 if ((prefixesWritten & prefixBit) == 0)
792 writer.WriteXmlnsAttribute(prefixString, headerWithSharedNamespace.SharedNamespace);
793 prefixesWritten |= prefixBit;
799 class OnWriteBodyContentsAsyncResult : ScheduleActionItemAsyncResult
802 XmlDictionaryWriter writer;
804 public OnWriteBodyContentsAsyncResult(XmlDictionaryWriter writer, Message message, AsyncCallback callback, object state)
805 : base(callback, state)
807 Fx.Assert(message != null, "message should never be null");
809 this.message = message;
810 this.writer = writer;
815 protected override void OnDoWork()
817 this.message.OnWriteBodyContents(this.writer);
821 class OnWriteMessageAsyncResult : ScheduleActionItemAsyncResult
824 XmlDictionaryWriter writer;
826 public OnWriteMessageAsyncResult(XmlDictionaryWriter writer, Message message, AsyncCallback callback, object state)
827 : base(callback, state)
829 Fx.Assert(message != null, "message should never be null");
831 this.message = message;
832 this.writer = writer;
837 protected override void OnDoWork()
839 this.message.OnWriteMessage(this.writer);
844 class EmptyBodyWriter : BodyWriter
846 static EmptyBodyWriter value;
853 public static EmptyBodyWriter Value
858 value = new EmptyBodyWriter();
863 internal override bool IsEmpty
868 protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
873 class FaultBodyWriter : BodyWriter
876 EnvelopeVersion version;
878 public FaultBodyWriter(MessageFault fault, EnvelopeVersion version)
882 this.version = version;
885 internal override bool IsFault
890 protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
892 fault.WriteTo(writer, version);
896 class XmlObjectSerializerBodyWriter : BodyWriter
899 XmlObjectSerializer serializer;
901 public XmlObjectSerializerBodyWriter(object body, XmlObjectSerializer serializer)
905 this.serializer = serializer;
913 protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
917 serializer.WriteObject(writer, body);
922 class XmlReaderBodyWriter : BodyWriter
924 XmlDictionaryReader reader;
927 public XmlReaderBodyWriter(XmlDictionaryReader reader, EnvelopeVersion version)
930 this.reader = reader;
931 if (reader.MoveToContent() != XmlNodeType.Element)
932 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidReaderPositionOnCreateMessage), "reader"));
934 this.isFault = Message.IsFaultStartElement(reader, version);
937 internal override bool IsFault
945 protected override BodyWriter OnCreateBufferedCopy(int maxBufferSize)
947 return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
950 protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
954 XmlNodeType type = reader.MoveToContent();
955 while (!reader.EOF && type != XmlNodeType.EndElement)
957 if (type != XmlNodeType.Element)
958 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidReaderPositionOnCreateMessage), "reader"));
959 writer.WriteNode(reader, false);
961 type = reader.MoveToContent();
967 class BodyWriterMessage : Message
969 MessageProperties properties;
970 MessageHeaders headers;
971 BodyWriter bodyWriter;
973 BodyWriterMessage(BodyWriter bodyWriter)
975 this.bodyWriter = bodyWriter;
978 public BodyWriterMessage(MessageVersion version, string action, BodyWriter bodyWriter)
981 this.headers = new MessageHeaders(version);
982 this.headers.Action = action;
985 public BodyWriterMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter bodyWriter)
988 this.headers = new MessageHeaders(version);
989 this.headers.SetActionHeader(actionHeader);
992 public BodyWriterMessage(MessageHeaders headers, KeyValuePair<string, object>[] properties, BodyWriter bodyWriter)
995 this.headers = new MessageHeaders(headers);
996 this.properties = new MessageProperties(properties);
999 public override bool IsFault
1004 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1005 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1006 return bodyWriter.IsFault;
1010 public override bool IsEmpty
1015 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1016 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1017 return bodyWriter.IsEmpty;
1021 public override MessageHeaders Headers
1026 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1027 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1032 public override MessageProperties Properties
1037 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1038 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1039 if (properties == null)
1040 properties = new MessageProperties();
1045 internal override void SetProperty(string name, object value)
1047 MessageProperties prop = this.properties;
1055 internal override bool GetProperty(string name, out object result)
1057 MessageProperties prop = this.properties;
1061 return prop.TryGetValue(name, out result);
1069 public override MessageVersion Version
1074 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1075 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1076 return headers.MessageVersion;
1080 protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
1082 BodyWriter bufferedBodyWriter;
1083 if (bodyWriter.IsBuffered)
1085 bufferedBodyWriter = bodyWriter;
1089 bufferedBodyWriter = bodyWriter.CreateBufferedCopy(maxBufferSize);
1091 KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
1092 ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
1093 return new BodyWriterMessageBuffer(headers, properties, bufferedBodyWriter);
1096 protected override void OnClose()
1098 Exception ex = null;
1112 if (properties != null)
1113 properties.Dispose();
1124 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
1129 protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
1131 bodyWriter.WriteBodyContents(writer);
1134 protected override IAsyncResult OnBeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
1136 WriteMessagePreamble(writer);
1137 return new OnWriteMessageAsyncResult(writer, this, callback, state);
1140 protected override void OnEndWriteMessage(IAsyncResult result)
1142 OnWriteMessageAsyncResult.End(result);
1145 protected override IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
1147 return bodyWriter.BeginWriteBodyContents(writer, callback, state);
1150 protected override void OnEndWriteBodyContents(IAsyncResult result)
1152 bodyWriter.EndWriteBodyContents(result);
1155 protected override void OnBodyToString(XmlDictionaryWriter writer)
1157 if (bodyWriter.IsBuffered)
1159 bodyWriter.WriteBodyContents(writer);
1163 writer.WriteString(SR.GetString(SR.MessageBodyIsStream));
1167 protected internal BodyWriter BodyWriter
1175 class OnWriteMessageAsyncResult : AsyncResult
1177 BodyWriterMessage message;
1178 XmlDictionaryWriter writer;
1180 public OnWriteMessageAsyncResult(XmlDictionaryWriter writer, BodyWriterMessage message, AsyncCallback callback, object state)
1181 : base(callback, state)
1183 this.message = message;
1184 this.writer = writer;
1186 if (HandleWriteBodyContents(null))
1188 this.Complete(true);
1192 bool HandleWriteBodyContents(IAsyncResult result)
1196 result = this.message.OnBeginWriteBodyContents(this.writer, PrepareAsyncCompletion(HandleWriteBodyContents), this);
1197 if (!result.CompletedSynchronously)
1203 this.message.OnEndWriteBodyContents(result);
1204 this.message.WriteMessagePostamble(this.writer);
1208 public static void End(IAsyncResult result)
1210 AsyncResult.End<OnWriteMessageAsyncResult>(result);
1216 abstract class ReceivedMessage : Message
1221 public override bool IsEmpty
1223 get { return isEmpty; }
1226 public override bool IsFault
1228 get { return isFault; }
1231 protected static bool HasHeaderElement(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
1233 return reader.IsStartElement(XD.MessageDictionary.Header, envelopeVersion.DictionaryNamespace);
1236 protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
1240 using (XmlDictionaryReader bodyReader = OnGetReaderAtBodyContents())
1242 if (bodyReader.ReadState == ReadState.Error || bodyReader.ReadState == ReadState.Closed)
1243 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageBodyReaderInvalidReadState, bodyReader.ReadState.ToString())));
1245 while (bodyReader.NodeType != XmlNodeType.EndElement && !bodyReader.EOF)
1247 writer.WriteNode(bodyReader, false);
1250 this.ReadFromBodyContentsToEnd(bodyReader);
1255 protected bool ReadStartBody(XmlDictionaryReader reader)
1257 return Message.ReadStartBody(reader, this.Version.Envelope, out this.isFault, out this.isEmpty);
1260 protected static EnvelopeVersion ReadStartEnvelope(XmlDictionaryReader reader)
1262 EnvelopeVersion envelopeVersion;
1264 if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message12Dictionary.Namespace))
1265 envelopeVersion = EnvelopeVersion.Soap12;
1266 else if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message11Dictionary.Namespace))
1267 envelopeVersion = EnvelopeVersion.Soap11;
1269 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageVersionUnknown)));
1270 if (reader.IsEmptyElement)
1271 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageBodyMissing)));
1273 return envelopeVersion;
1276 protected static void VerifyStartBody(XmlDictionaryReader reader, EnvelopeVersion version)
1278 if (!reader.IsStartElement(XD.MessageDictionary.Body, version.DictionaryNamespace))
1279 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageBodyMissing)));
1283 sealed class StreamedMessage : ReceivedMessage
1285 MessageHeaders headers;
1286 XmlAttributeHolder[] envelopeAttributes;
1287 XmlAttributeHolder[] headerAttributes;
1288 XmlAttributeHolder[] bodyAttributes;
1289 string envelopePrefix;
1290 string headerPrefix;
1292 MessageProperties properties;
1293 XmlDictionaryReader reader;
1294 XmlDictionaryReaderQuotas quotas;
1296 public StreamedMessage(XmlDictionaryReader reader, int maxSizeOfHeaders, MessageVersion desiredVersion)
1298 properties = new MessageProperties();
1299 if (reader.NodeType != XmlNodeType.Element)
1300 reader.MoveToContent();
1302 if (desiredVersion.Envelope == EnvelopeVersion.None)
1304 this.reader = reader;
1305 this.headerAttributes = XmlAttributeHolder.emptyArray;
1306 this.headers = new MessageHeaders(desiredVersion);
1310 envelopeAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
1311 envelopePrefix = reader.Prefix;
1312 EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
1313 if (desiredVersion.Envelope != envelopeVersion)
1315 Exception versionMismatchException = new ArgumentException(SR.GetString(SR.EncoderEnvelopeVersionMismatch, envelopeVersion, desiredVersion.Envelope), "reader");
1316 throw TraceUtility.ThrowHelperError(
1317 new CommunicationException(versionMismatchException.Message, versionMismatchException),
1321 if (HasHeaderElement(reader, envelopeVersion))
1323 headerPrefix = reader.Prefix;
1324 headerAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
1325 headers = new MessageHeaders(desiredVersion, reader, envelopeAttributes, headerAttributes, ref maxSizeOfHeaders);
1329 headerAttributes = XmlAttributeHolder.emptyArray;
1330 headers = new MessageHeaders(desiredVersion);
1333 if (reader.NodeType != XmlNodeType.Element)
1334 reader.MoveToContent();
1335 bodyPrefix = reader.Prefix;
1336 VerifyStartBody(reader, envelopeVersion);
1337 bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
1338 if (ReadStartBody(reader))
1340 this.reader = reader;
1344 this.quotas = new XmlDictionaryReaderQuotas();
1345 reader.Quotas.CopyTo(this.quotas);
1351 public override MessageHeaders Headers
1356 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1357 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1362 public override MessageVersion Version
1366 return headers.MessageVersion;
1370 public override MessageProperties Properties
1378 protected override void OnBodyToString(XmlDictionaryWriter writer)
1380 writer.WriteString(SR.GetString(SR.MessageBodyIsStream));
1383 protected override void OnClose()
1385 Exception ex = null;
1399 properties.Dispose();
1425 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
1428 protected override XmlDictionaryReader OnGetReaderAtBodyContents()
1430 XmlDictionaryReader reader = this.reader;
1435 protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
1437 if (this.reader != null)
1438 return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
1439 return OnCreateBufferedCopy(maxBufferSize, this.quotas);
1442 protected override void OnWriteStartBody(XmlDictionaryWriter writer)
1444 writer.WriteStartElement(bodyPrefix, MessageStrings.Body, Version.Envelope.Namespace);
1445 XmlAttributeHolder.WriteAttributes(bodyAttributes, writer);
1448 protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
1450 EnvelopeVersion envelopeVersion = Version.Envelope;
1451 writer.WriteStartElement(envelopePrefix, MessageStrings.Envelope, envelopeVersion.Namespace);
1452 XmlAttributeHolder.WriteAttributes(envelopeAttributes, writer);
1455 protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
1457 EnvelopeVersion envelopeVersion = Version.Envelope;
1458 writer.WriteStartElement(headerPrefix, MessageStrings.Header, envelopeVersion.Namespace);
1459 XmlAttributeHolder.WriteAttributes(headerAttributes, writer);
1462 protected override string OnGetBodyAttribute(string localName, string ns)
1464 return XmlAttributeHolder.GetAttribute(bodyAttributes, localName, ns);
1468 interface IBufferedMessageData
1470 MessageEncoder MessageEncoder { get; }
1471 ArraySegment<byte> Buffer { get; }
1472 XmlDictionaryReaderQuotas Quotas { get; }
1474 void EnableMultipleUsers();
1475 XmlDictionaryReader GetMessageReader();
1477 void ReturnMessageState(RecycledMessageState messageState);
1478 RecycledMessageState TakeMessageState();
1481 sealed class BufferedMessage : ReceivedMessage
1483 MessageHeaders headers;
1484 MessageProperties properties;
1485 IBufferedMessageData messageData;
1486 RecycledMessageState recycledMessageState;
1487 XmlDictionaryReader reader;
1488 XmlAttributeHolder[] bodyAttributes;
1490 public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState)
1491 : this(messageData, recycledMessageState, null, false)
1495 public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, bool[] understoodHeaders, bool understoodHeadersModified)
1497 bool throwing = true;
1500 this.recycledMessageState = recycledMessageState;
1501 this.messageData = messageData;
1502 properties = recycledMessageState.TakeProperties();
1503 if (properties == null)
1504 this.properties = new MessageProperties();
1505 XmlDictionaryReader reader = messageData.GetMessageReader();
1506 MessageVersion desiredVersion = messageData.MessageEncoder.MessageVersion;
1508 if (desiredVersion.Envelope == EnvelopeVersion.None)
1510 this.reader = reader;
1511 this.headers = new MessageHeaders(desiredVersion);
1515 EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
1516 if (desiredVersion.Envelope != envelopeVersion)
1518 Exception versionMismatchException = new ArgumentException(SR.GetString(SR.EncoderEnvelopeVersionMismatch, envelopeVersion, desiredVersion.Envelope), "reader");
1519 throw TraceUtility.ThrowHelperError(
1520 new CommunicationException(versionMismatchException.Message, versionMismatchException),
1524 if (HasHeaderElement(reader, envelopeVersion))
1526 headers = recycledMessageState.TakeHeaders();
1527 if (headers == null)
1529 headers = new MessageHeaders(desiredVersion, reader, messageData, recycledMessageState, understoodHeaders, understoodHeadersModified);
1533 headers.Init(desiredVersion, reader, messageData, recycledMessageState, understoodHeaders, understoodHeadersModified);
1538 headers = new MessageHeaders(desiredVersion);
1541 VerifyStartBody(reader, envelopeVersion);
1543 int maxSizeOfAttributes = int.MaxValue;
1544 bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfAttributes);
1545 if (maxSizeOfAttributes < int.MaxValue - 4096)
1546 bodyAttributes = null;
1547 if (ReadStartBody(reader))
1549 this.reader = reader;
1560 if (throwing && MessageLogger.LoggingEnabled)
1562 MessageLogger.LogMessage(messageData.Buffer, MessageLoggingSource.Malformed);
1567 public override MessageHeaders Headers
1572 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1573 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1578 internal IBufferedMessageData MessageData
1586 public override MessageProperties Properties
1591 #pragma warning suppress 56503 // Microsoft, Invalid State after dispose
1592 throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
1597 internal override RecycledMessageState RecycledMessageState
1599 get { return recycledMessageState; }
1602 public override MessageVersion Version
1606 return headers.MessageVersion;
1610 protected override XmlDictionaryReader OnGetReaderAtBodyContents()
1612 XmlDictionaryReader reader = this.reader;
1617 internal override XmlDictionaryReader GetReaderAtHeader()
1619 if (!headers.ContainsOnlyBufferedMessageHeaders)
1620 return base.GetReaderAtHeader();
1621 XmlDictionaryReader reader = messageData.GetMessageReader();
1622 if (reader.NodeType != XmlNodeType.Element)
1623 reader.MoveToContent();
1625 if (HasHeaderElement(reader, headers.MessageVersion.Envelope))
1627 return base.GetReaderAtHeader();
1630 public XmlDictionaryReader GetBufferedReaderAtBody()
1632 XmlDictionaryReader reader = messageData.GetMessageReader();
1633 if (reader.NodeType != XmlNodeType.Element)
1634 reader.MoveToContent();
1635 if (this.Version.Envelope != EnvelopeVersion.None)
1638 if (HasHeaderElement(reader, headers.MessageVersion.Envelope))
1640 if (reader.NodeType != XmlNodeType.Element)
1641 reader.MoveToContent();
1646 public XmlDictionaryReader GetMessageReader()
1648 return messageData.GetMessageReader();
1651 protected override void OnBodyToString(XmlDictionaryWriter writer)
1653 using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
1655 if (this.Version == MessageVersion.None)
1657 writer.WriteNode(reader, false);
1661 if (!reader.IsEmptyElement)
1663 reader.ReadStartElement();
1664 while (reader.NodeType != XmlNodeType.EndElement)
1665 writer.WriteNode(reader, false);
1671 protected override void OnClose()
1673 Exception ex = null;
1687 properties.Dispose();
1714 recycledMessageState.ReturnHeaders(headers);
1715 recycledMessageState.ReturnProperties(properties);
1716 messageData.ReturnMessageState(recycledMessageState);
1717 recycledMessageState = null;
1718 messageData.Close();
1730 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
1733 protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
1735 using (XmlDictionaryReader reader = GetMessageReader())
1737 reader.MoveToContent();
1738 EnvelopeVersion envelopeVersion = Version.Envelope;
1739 writer.WriteStartElement(reader.Prefix, MessageStrings.Envelope, envelopeVersion.Namespace);
1740 writer.WriteAttributes(reader, false);
1744 protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
1746 using (XmlDictionaryReader reader = GetMessageReader())
1748 reader.MoveToContent();
1749 EnvelopeVersion envelopeVersion = Version.Envelope;
1751 if (HasHeaderElement(reader, envelopeVersion))
1753 writer.WriteStartElement(reader.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
1754 writer.WriteAttributes(reader, false);
1758 writer.WriteStartElement(MessageStrings.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
1763 protected override void OnWriteStartBody(XmlDictionaryWriter writer)
1765 using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
1767 writer.WriteStartElement(reader.Prefix, MessageStrings.Body, Version.Envelope.Namespace);
1768 writer.WriteAttributes(reader, false);
1772 protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
1774 if (headers.ContainsOnlyBufferedMessageHeaders)
1776 KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
1777 ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
1778 messageData.EnableMultipleUsers();
1779 bool[] understoodHeaders = null;
1780 if (headers.HasMustUnderstandBeenModified)
1782 understoodHeaders = new bool[headers.Count];
1783 for (int i = 0; i < headers.Count; i++)
1785 understoodHeaders[i] = headers.IsUnderstood(i);
1788 return new BufferedMessageBuffer(messageData, properties, understoodHeaders, headers.HasMustUnderstandBeenModified);
1792 if (this.reader != null)
1793 return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
1794 return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max);
1798 protected override string OnGetBodyAttribute(string localName, string ns)
1800 if (this.bodyAttributes != null)
1801 return XmlAttributeHolder.GetAttribute(this.bodyAttributes, localName, ns);
1802 using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
1804 return reader.GetAttribute(localName, ns);
1809 struct XmlAttributeHolder
1816 public static XmlAttributeHolder[] emptyArray = new XmlAttributeHolder[0];
1818 public XmlAttributeHolder(string prefix, string localName, string ns, string value)
1820 this.prefix = prefix;
1821 this.localName = localName;
1826 public string Prefix
1828 get { return prefix; }
1831 public string NamespaceUri
1836 public string LocalName
1838 get { return localName; }
1843 get { return value; }
1846 public void WriteTo(XmlWriter writer)
1848 writer.WriteStartAttribute(prefix, localName, ns);
1849 writer.WriteString(value);
1850 writer.WriteEndAttribute();
1853 public static void WriteAttributes(XmlAttributeHolder[] attributes, XmlWriter writer)
1855 for (int i = 0; i < attributes.Length; i++)
1856 attributes[i].WriteTo(writer);
1859 public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader)
1861 int maxSizeOfHeaders = int.MaxValue;
1862 return ReadAttributes(reader, ref maxSizeOfHeaders);
1865 public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader, ref int maxSizeOfHeaders)
1867 if (reader.AttributeCount == 0)
1869 XmlAttributeHolder[] attributes = new XmlAttributeHolder[reader.AttributeCount];
1870 reader.MoveToFirstAttribute();
1871 for (int i = 0; i < attributes.Length; i++)
1873 string ns = reader.NamespaceURI;
1874 string localName = reader.LocalName;
1875 string prefix = reader.Prefix;
1876 string value = string.Empty;
1877 while (reader.ReadAttributeValue())
1879 if (value.Length == 0)
1880 value = reader.Value;
1882 value += reader.Value;
1884 Deduct(prefix, ref maxSizeOfHeaders);
1885 Deduct(localName, ref maxSizeOfHeaders);
1886 Deduct(ns, ref maxSizeOfHeaders);
1887 Deduct(value, ref maxSizeOfHeaders);
1888 attributes[i] = new XmlAttributeHolder(prefix, localName, ns, value);
1889 reader.MoveToNextAttribute();
1891 reader.MoveToElement();
1895 static void Deduct(string s, ref int maxSizeOfHeaders)
1897 int byteCount = s.Length * sizeof(char);
1898 if (byteCount > maxSizeOfHeaders)
1900 string message = SR.GetString(SR.XmlBufferQuotaExceeded);
1901 Exception inner = new QuotaExceededException(message);
1902 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(message, inner));
1904 maxSizeOfHeaders -= byteCount;
1907 public static string GetAttribute(XmlAttributeHolder[] attributes, string localName, string ns)
1909 for (int i = 0; i < attributes.Length; i++)
1910 if (attributes[i].LocalName == localName && attributes[i].NamespaceUri == ns)
1911 return attributes[i].Value;
1916 class RecycledMessageState
1918 MessageHeaders recycledHeaders;
1919 MessageProperties recycledProperties;
1921 HeaderInfoCache headerInfoCache;
1923 public HeaderInfoCache HeaderInfoCache
1927 if (headerInfoCache == null)
1929 headerInfoCache = new HeaderInfoCache();
1931 return headerInfoCache;
1935 public UriCache UriCache
1939 if (uriCache == null)
1940 uriCache = new UriCache();
1945 public MessageProperties TakeProperties()
1947 MessageProperties taken = recycledProperties;
1948 recycledProperties = null;
1952 public void ReturnProperties(MessageProperties properties)
1954 if (properties.CanRecycle)
1956 properties.Recycle();
1957 this.recycledProperties = properties;
1961 public MessageHeaders TakeHeaders()
1963 MessageHeaders taken = recycledHeaders;
1964 recycledHeaders = null;
1968 public void ReturnHeaders(MessageHeaders headers)
1970 if (headers.CanRecycle)
1972 headers.Recycle(this.HeaderInfoCache);
1973 this.recycledHeaders = headers;
1978 class HeaderInfoCache
1980 const int maxHeaderInfos = 4;
1981 HeaderInfo[] headerInfos;
1984 public MessageHeaderInfo TakeHeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isRefParam)
1986 if (this.headerInfos != null)
1991 HeaderInfo headerInfo = this.headerInfos[i];
1992 if (headerInfo != null)
1994 if (headerInfo.Matches(reader, actor, mustUnderstand, relay, isRefParam))
1996 this.headerInfos[i] = null;
1997 this.index = (i + 1) % maxHeaderInfos;
2001 i = (i + 1) % maxHeaderInfos;
2002 if (i == this.index)
2009 return new HeaderInfo(reader, actor, mustUnderstand, relay, isRefParam);
2012 public void ReturnHeaderInfo(MessageHeaderInfo headerInfo)
2014 HeaderInfo headerInfoToReturn = headerInfo as HeaderInfo;
2015 if (headerInfoToReturn != null)
2017 if (this.headerInfos == null)
2019 this.headerInfos = new HeaderInfo[maxHeaderInfos];
2024 if (this.headerInfos[i] == null)
2028 i = (i + 1) % maxHeaderInfos;
2029 if (i == this.index)
2034 this.headerInfos[i] = headerInfoToReturn;
2035 this.index = (i + 1) % maxHeaderInfos;
2039 class HeaderInfo : MessageHeaderInfo
2044 bool isReferenceParameter;
2045 bool mustUnderstand;
2048 public HeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isReferenceParameter)
2051 this.mustUnderstand = mustUnderstand;
2053 this.isReferenceParameter = isReferenceParameter;
2054 reader.GetNonAtomizedNames(out name, out ns);
2057 public override string Name
2059 get { return name; }
2062 public override string Namespace
2067 public override bool IsReferenceParameter
2069 get { return isReferenceParameter; }
2072 public override string Actor
2074 get { return actor; }
2077 public override bool MustUnderstand
2079 get { return mustUnderstand; }
2082 public override bool Relay
2084 get { return relay; }
2087 public bool Matches(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isRefParam)
2089 return reader.IsStartElement(this.name, this.ns) &&
2090 this.actor == actor && this.mustUnderstand == mustUnderstand && this.relay == relay && this.isReferenceParameter == isRefParam;
2097 const int MaxKeyLength = 128;
2098 const int MaxEntries = 8;
2104 entries = new Entry[MaxEntries];
2107 public Uri CreateUri(string uriString)
2109 Uri uri = Get(uriString);
2112 uri = new Uri(uriString);
2113 Set(uriString, uri);
2120 if (key.Length > MaxKeyLength)
2122 for (int i = count - 1; i >= 0; i--)
2123 if (entries[i].Key == key)
2124 return entries[i].Value;
2128 void Set(string key, Uri value)
2130 if (key.Length > MaxKeyLength)
2132 if (count < entries.Length)
2134 entries[count++] = new Entry(key, value);
2138 Array.Copy(entries, 1, entries, 0, entries.Length - 1);
2139 entries[count - 1] = new Entry(key, value);
2148 public Entry(string key, Uri value)
2161 get { return value; }