Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / Message.cs / 1 / Message.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Dispatcher; using System.Collections.Specialized; using System.Globalization; using System.IO; using System.Runtime.Serialization; using System.ServiceModel.Diagnostics; using System.Xml; using System.Xml.Serialization; using System.Diagnostics; public abstract class Message : IDisposable { MessageState state; SeekableMessageNavigator messageNavigator; internal const int InitialBufferSize = 1024; public abstract MessageHeaders Headers { get; } // must never return null protected bool IsDisposed { get { return state == MessageState.Closed; } } public virtual bool IsFault { get { if (IsDisposed) #pragma warning suppress 56503 // [....], Invalid State after dispose throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); return false; } } public virtual bool IsEmpty { get { if (IsDisposed) #pragma warning suppress 56503 // [....], Invalid State after dispose throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); return false; } } public abstract MessageProperties Properties { get; } public abstract MessageVersion Version { get; } // must never return null internal virtual RecycledMessageState RecycledMessageState { get { return null; } } public MessageState State { get { return state; } } internal void BodyToString(XmlDictionaryWriter writer) { OnBodyToString(writer); } public void Close() { if (state != MessageState.Closed) { ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? TraceUtility.ExtractAndRemoveActivity(this) : null; state = MessageState.Closed; OnClose(); if (DiagnosticUtility.ShouldTraceVerbose) { Guid guid = activity == null ? Guid.Empty : activity.Id; DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosed, SR.GetString(SR.TraceCodeMessageClosed), null, null, guid, this); } } else { if (DiagnosticUtility.ShouldTraceVerbose) { TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosedAgain, (object)this, this); } } } public MessageBuffer CreateBufferedCopy(int maxBufferSize) { if (maxBufferSize < 0) throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxBufferSize", maxBufferSize, SR.GetString(SR.ValueMustBeNonNegative)), this); switch (state) { case MessageState.Created: state = MessageState.Copied; if (DiagnosticUtility.ShouldTraceVerbose) { TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageCopied, this, this); } break; case MessageState.Closed: throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); case MessageState.Copied: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this); case MessageState.Read: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this); case MessageState.Written: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this); default: DiagnosticUtility.DebugAssert(SR.GetString(SR.InvalidMessageState)); throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this); } return OnCreateBufferedCopy(maxBufferSize); } static Type GetObjectType(object value) { return (value == null) ? typeof(object) : value.GetType(); } static public Message CreateMessage(MessageVersion version, string action, object body) { return CreateMessage(version, action, body, DataContractSerializerDefaults.CreateSerializer(GetObjectType(body), int.MaxValue/*maxItems*/)); } static public Message CreateMessage(MessageVersion version, string action, object body, XmlObjectSerializer serializer) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); if (serializer == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer")); return new BodyWriterMessage(version, action, new XmlObjectSerializerBodyWriter(body, serializer)); } static public Message CreateMessage(MessageVersion version, string action, XmlReader body) { return CreateMessage(version, action, XmlDictionaryReader.CreateDictionaryReader(body)); } static public Message CreateMessage(MessageVersion version, string action, XmlDictionaryReader body) { if (body == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("body"); if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version"); return CreateMessage(version, action, new XmlReaderBodyWriter(body, version.Envelope)); } static public Message CreateMessage(MessageVersion version, string action, BodyWriter body) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); if (body == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("body")); return new BodyWriterMessage(version, action, body); } static internal Message CreateMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter body) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); if (body == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("body")); return new BodyWriterMessage(version, actionHeader, body); } static public Message CreateMessage(MessageVersion version, string action) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); return new BodyWriterMessage(version, action, EmptyBodyWriter.Value); } static internal Message CreateMessage(MessageVersion version, ActionHeader actionHeader) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); return new BodyWriterMessage(version, actionHeader, EmptyBodyWriter.Value); } static public Message CreateMessage(XmlReader envelopeReader, int maxSizeOfHeaders, MessageVersion version) { return CreateMessage(XmlDictionaryReader.CreateDictionaryReader(envelopeReader), maxSizeOfHeaders, version); } static public Message CreateMessage(XmlDictionaryReader envelopeReader, int maxSizeOfHeaders, MessageVersion version) { if (envelopeReader == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("envelopeReader")); if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); Message message = new StreamedMessage(envelopeReader, maxSizeOfHeaders, version); return message; } static public Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, string action) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); if (faultCode == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faultCode")); if (reason == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason")); return CreateMessage(version, MessageFault.CreateFault(faultCode, reason), action); } static public Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, object detail, string action) { if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); if (faultCode == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faultCode")); if (reason == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason")); return CreateMessage(version, MessageFault.CreateFault(faultCode, new FaultReason(reason), detail), action); } static public Message CreateMessage(MessageVersion version, MessageFault fault, string action) { if (fault == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("fault")); if (version == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version")); return new BodyWriterMessage(version, action, new FaultBodyWriter(fault, version.Envelope)); } internal Exception CreateMessageDisposedException() { return new ObjectDisposedException("", SR.GetString(SR.MessageClosed)); } void IDisposable.Dispose() { Close(); } public T GetBody() { return GetBody (DataContractSerializerDefaults.CreateSerializer(typeof(T), int.MaxValue/*maxItems*/)); } public T GetBody (XmlObjectSerializer serializer) { if (serializer == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer")); T value; using (XmlDictionaryReader reader = GetReaderAtBodyContents()) { value = (T)serializer.ReadObject(reader); this.ReadFromBodyContentsToEnd(reader); } return value; } internal virtual XmlDictionaryReader GetReaderAtHeader() { XmlBuffer buffer = new XmlBuffer(int.MaxValue); XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max); WriteStartEnvelope(writer); MessageHeaders headers = this.Headers; for (int i = 0; i < headers.Count; i++) headers.WriteHeader(i, writer); writer.WriteEndElement(); writer.WriteEndElement(); buffer.CloseSection(); buffer.Close(); XmlDictionaryReader reader = buffer.GetReader(0); reader.ReadStartElement(); reader.MoveToStartElement(); return reader; } public XmlDictionaryReader GetReaderAtBodyContents() { switch (state) { case MessageState.Created: state = MessageState.Read; if (DiagnosticUtility.ShouldTraceVerbose) { TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageRead, this); } break; case MessageState.Copied: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this); case MessageState.Read: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this); case MessageState.Written: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this); case MessageState.Closed: throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); default: DiagnosticUtility.DebugAssert(SR.GetString(SR.InvalidMessageState)); throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this); } if (IsEmpty) throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageIsEmpty)), this); return OnGetReaderAtBodyContents(); } internal SeekableMessageNavigator GetNavigator(bool navigateBody, int maxNodes) { if (IsDisposed) throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); if (null == this.messageNavigator) { this.messageNavigator = new SeekableMessageNavigator(this, maxNodes, XmlSpace.Default, navigateBody, false); } else { this.messageNavigator.ForkNodeCount(maxNodes); } return this.messageNavigator; } internal void InitializeReply(Message request) { UniqueId requestMessageID = request.Headers.MessageId; if (requestMessageID == null) throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.RequestMessageDoesNotHaveAMessageID)), request); Headers.RelatesTo = requestMessageID; } static internal bool IsFaultStartElement(XmlDictionaryReader reader, EnvelopeVersion version) { return reader.IsStartElement(XD.MessageDictionary.Fault, version.DictionaryNamespace); } protected virtual void OnBodyToString(XmlDictionaryWriter writer) { writer.WriteString(SR.GetString(SR.MessageBodyIsUnknown)); } protected virtual MessageBuffer OnCreateBufferedCopy(int maxBufferSize) { return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max); } internal MessageBuffer OnCreateBufferedCopy(int maxBufferSize, XmlDictionaryReaderQuotas quotas) { XmlBuffer msgBuffer = new XmlBuffer(maxBufferSize); XmlDictionaryWriter writer = msgBuffer.OpenSection(quotas); OnWriteMessage(writer); msgBuffer.CloseSection(); msgBuffer.Close(); return new DefaultMessageBuffer(this, msgBuffer); } protected virtual void OnClose() { } protected virtual XmlDictionaryReader OnGetReaderAtBodyContents() { XmlBuffer bodyBuffer = new XmlBuffer(int.MaxValue); XmlDictionaryWriter writer = bodyBuffer.OpenSection(XmlDictionaryReaderQuotas.Max); if (this.Version.Envelope != EnvelopeVersion.None) { OnWriteStartEnvelope(writer); OnWriteStartBody(writer); } OnWriteBodyContents(writer); if (this.Version.Envelope != EnvelopeVersion.None) { writer.WriteEndElement(); writer.WriteEndElement(); } bodyBuffer.CloseSection(); bodyBuffer.Close(); XmlDictionaryReader reader = bodyBuffer.GetReader(0); if (this.Version.Envelope != EnvelopeVersion.None) { reader.ReadStartElement(); reader.ReadStartElement(); } reader.MoveToContent(); return reader; } protected virtual void OnWriteStartBody(XmlDictionaryWriter writer) { MessageDictionary messageDictionary = XD.MessageDictionary; writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Body, Version.Envelope.DictionaryNamespace); } public void WriteBodyContents(XmlDictionaryWriter writer) { if (writer == null) throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this); switch (state) { case MessageState.Created: state = MessageState.Written; if (DiagnosticUtility.ShouldTraceVerbose) { TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageWritten, this); } break; case MessageState.Copied: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this); case MessageState.Read: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this); case MessageState.Written: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this); case MessageState.Closed: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateMessageDisposedException()); default: DiagnosticUtility.DebugAssert(SR.GetString(SR.InvalidMessageState)); throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this); } OnWriteBodyContents(writer); } protected abstract void OnWriteBodyContents(XmlDictionaryWriter writer); public void WriteStartEnvelope(XmlDictionaryWriter writer) { if (writer == null) throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this); OnWriteStartEnvelope(writer); } protected virtual void OnWriteStartEnvelope(XmlDictionaryWriter writer) { EnvelopeVersion envelopeVersion = Version.Envelope; if (envelopeVersion != EnvelopeVersion.None) { MessageDictionary messageDictionary = XD.MessageDictionary; writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Envelope, envelopeVersion.DictionaryNamespace); WriteSharedHeaderPrefixes(writer); } } protected virtual void OnWriteStartHeaders(XmlDictionaryWriter writer) { EnvelopeVersion envelopeVersion = Version.Envelope; if (envelopeVersion != EnvelopeVersion.None) { MessageDictionary messageDictionary = XD.MessageDictionary; writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Header, envelopeVersion.DictionaryNamespace); } } public override string ToString() { if (IsDisposed) throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); XmlTextWriter textWriter = new XmlTextWriter(stringWriter); textWriter.Formatting = Formatting.Indented; XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(textWriter); try { ToString(writer); writer.Flush(); return stringWriter.ToString(); } catch (XmlException e) { return SR.GetString(SR.MessageBodyToStringError, e.GetType().ToString(), e.Message); } } internal void ToString(XmlDictionaryWriter writer) { if (IsDisposed) { throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); } if (this.Version.Envelope != EnvelopeVersion.None) { WriteStartEnvelope(writer); WriteStartHeaders(writer); MessageHeaders headers = this.Headers; for (int i = 0; i < headers.Count; i++) { headers.WriteHeader(i, writer); } writer.WriteEndElement(); MessageDictionary messageDictionary = XD.MessageDictionary; WriteStartBody(writer); } BodyToString(writer); if (this.Version.Envelope != EnvelopeVersion.None) { writer.WriteEndElement(); writer.WriteEndElement(); } } public string GetBodyAttribute(string localName, string ns) { if (localName == null) throw TraceUtility.ThrowHelperError(new ArgumentNullException("localName"), this); if (ns == null) throw TraceUtility.ThrowHelperError(new ArgumentNullException("ns"), this); switch (state) { case MessageState.Created: break; case MessageState.Copied: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this); case MessageState.Read: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this); case MessageState.Written: throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this); case MessageState.Closed: throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this); default: DiagnosticUtility.DebugAssert(SR.GetString(SR.InvalidMessageState)); throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this); } return OnGetBodyAttribute(localName, ns); } protected virtual string OnGetBodyAttribute(string localName, string ns) { return null; } internal void ReadFromBodyContentsToEnd(XmlDictionaryReader reader) { Message.ReadFromBodyContentsToEnd(reader, this.Version.Envelope); } static void ReadFromBodyContentsToEnd(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion) { if (envelopeVersion != EnvelopeVersion.None) { reader.ReadEndElement(); //