| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Globalization;
- using System.IO;
- using System.Runtime;
- using System.Runtime.Serialization;
- using System.ServiceModel;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Dispatcher;
- using System.Threading;
- using System.Xml;
- 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)
- {
- state = MessageState.Closed;
- OnClose();
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosed,
- SR.GetString(SR.TraceCodeMessageClosed), this);
- }
- }
- else
- {
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosedAgain,
- SR.GetString(SR.TraceCodeMessageClosedAgain), 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,
- SR.GetString(SR.TraceCodeMessageCopied), 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:
- Fx.Assert(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<T>()
- {
- XmlDictionaryReader reader = GetReaderAtBodyContents(); // This call will change the message state to Read.
- return OnGetBody<T>(reader);
- }
- protected virtual T OnGetBody<T>(XmlDictionaryReader reader)
- {
- return this.GetBodyCore<T>(reader, DataContractSerializerDefaults.CreateSerializer(typeof(T), int.MaxValue/*maxItems*/));
- }
- public T GetBody<T>(XmlObjectSerializer serializer)
- {
- if (serializer == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
- return this.GetBodyCore<T>(GetReaderAtBodyContents(), serializer);
- }
- T GetBodyCore<T>(XmlDictionaryReader reader, XmlObjectSerializer serializer)
- {
- T value;
- using (reader)
- {
- 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()
- {
- EnsureReadMessageState();
- if (IsEmpty)
- throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageIsEmpty)), this);
- return OnGetReaderAtBodyContents();
- }
- internal void EnsureReadMessageState()
- {
- switch (state)
- {
- case MessageState.Created:
- state = MessageState.Read;
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageRead, SR.GetString(SR.TraceCodeMessageRead), 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:
- Fx.Assert(SR.GetString(SR.InvalidMessageState));
- throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
- }
- }
- 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)
- {
- EnsureWriteMessageState(writer);
- OnWriteBodyContents(writer);
- }
- public IAsyncResult BeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
- {
- EnsureWriteMessageState(writer);
- return this.OnBeginWriteBodyContents(writer, callback, state);
- }
- public void EndWriteBodyContents(IAsyncResult result)
- {
- this.OnEndWriteBodyContents(result);
- }
- protected abstract void OnWriteBodyContents(XmlDictionaryWriter writer);
- protected virtual IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
- {
- return new OnWriteBodyContentsAsyncResult(writer, this, callback, state);
- }
- protected virtual void OnEndWriteBodyContents(IAsyncResult result)
- {
- OnWriteBodyContentsAsyncResult.End(result);
- }
- 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)
- {
- return base.ToString();
- }
- StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
- EncodingFallbackAwareXmlTextWriter textWriter = new EncodingFallbackAwareXmlTextWriter(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:
- Fx.Assert(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(); // </Body>
- reader.ReadEndElement(); // </Envelope>
- }
- reader.MoveToContent();
- }
- internal static bool ReadStartBody(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion, out bool isFault, out bool isEmpty)
- {
- if (reader.IsEmptyElement)
- {
- reader.Read();
- isEmpty = true;
- isFault = false;
- reader.ReadEndElement();
- return false;
- }
- else
- {
- reader.Read();
- if (reader.NodeType != XmlNodeType.Element)
- reader.MoveToContent();
- if (reader.NodeType == XmlNodeType.Element)
- {
- isFault = IsFaultStartElement(reader, envelopeVersion);
- isEmpty = false;
- }
- else if (reader.NodeType == XmlNodeType.EndElement)
- {
- isEmpty = true;
- isFault = false;
- Message.ReadFromBodyContentsToEnd(reader, envelopeVersion);
- return false;
- }
- else
- {
- isEmpty = false;
- isFault = false;
- }
- return true;
- }
- }
- public void WriteBody(XmlWriter writer)
- {
- WriteBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
- }
- public void WriteBody(XmlDictionaryWriter writer)
- {
- WriteStartBody(writer);
- WriteBodyContents(writer);
- writer.WriteEndElement();
- }
- public void WriteStartBody(XmlWriter writer)
- {
- WriteStartBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
- }
- public void WriteStartBody(XmlDictionaryWriter writer)
- {
- if (writer == null)
- throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this);
- OnWriteStartBody(writer);
- }
- internal void WriteStartHeaders(XmlDictionaryWriter writer)
- {
- OnWriteStartHeaders(writer);
- }
- public void WriteMessage(XmlWriter writer)
- {
- WriteMessage(XmlDictionaryWriter.CreateDictionaryWriter(writer));
- }
- public void WriteMessage(XmlDictionaryWriter writer)
- {
- EnsureWriteMessageState(writer);
- OnWriteMessage(writer);
- }
- void EnsureWriteMessageState(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, SR.GetString(SR.TraceCodeMessageWritten), 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:
- Fx.Assert(SR.GetString(SR.InvalidMessageState));
- throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
- }
- }
- public IAsyncResult BeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
- {
- EnsureWriteMessageState(writer);
- return OnBeginWriteMessage(writer, callback, state);
- }
- public void EndWriteMessage(IAsyncResult result)
- {
- OnEndWriteMessage(result);
- }
- protected virtual void OnWriteMessage(XmlDictionaryWriter writer)
- {
- WriteMessagePreamble(writer);
- OnWriteBodyContents(writer);
- WriteMessagePostamble(writer);
- }
- internal void WriteMessagePreamble(XmlDictionaryWriter writer)
- {
- if (this.Version.Envelope != EnvelopeVersion.None)
- {
- OnWriteStartEnvelope(writer);
- MessageHeaders headers = this.Headers;
- int headersCount = headers.Count;
- if (headersCount > 0)
- {
- OnWriteStartHeaders(writer);
- for (int i = 0; i < headersCount; i++)
- {
- headers.WriteHeader(i, writer);
- }
- writer.WriteEndElement();
- }
- OnWriteStartBody(writer);
- }
- }
- internal void WriteMessagePostamble(XmlDictionaryWriter writer)
- {
- if (this.Version.Envelope != EnvelopeVersion.None)
- {
- writer.WriteEndElement();
- writer.WriteEndElement();
- }
- }
- protected virtual IAsyncResult OnBeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
- {
- return new OnWriteMessageAsyncResult(writer, this, callback, state);
- }
- protected virtual void OnEndWriteMessage(IAsyncResult result)
- {
- OnWriteMessageAsyncResult.End(result);
- }
- void WriteSharedHeaderPrefixes(XmlDictionaryWriter writer)
- {
- MessageHeaders headers = Headers;
- int count = headers.Count;
- int prefixesWritten = 0;
- for (int i = 0; i < count; i++)
- {
- if (this.Version.Addressing == AddressingVersion.None && headers[i].Namespace == AddressingVersion.None.Namespace)
- {
- continue;
- }
- IMessageHeaderWithSharedNamespace headerWithSharedNamespace = headers[i] as IMessageHeaderWithSharedNamespace;
- if (headerWithSharedNamespace != null)
- {
- XmlDictionaryString prefix = headerWithSharedNamespace.SharedPrefix;
- string prefixString = prefix.Value;
- if (!((prefixString.Length == 1)))
- {
- Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixString.Length == 1) -- IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.");
- throw TraceUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.")), this);
- }
- int prefixIndex = prefixString[0] - 'a';
- if (!((prefixIndex >= 0 && prefixIndex < 26)))
- {
- Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixIndex >= 0 && prefixIndex < 26) -- IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.");
- throw TraceUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.")), this);
- }
- int prefixBit = 1 << prefixIndex;
- if ((prefixesWritten & prefixBit) == 0)
- {
- writer.WriteXmlnsAttribute(prefixString, headerWithSharedNamespace.SharedNamespace);
- prefixesWritten |= prefixBit;
- }
- }
- }
- }
- class OnWriteBodyContentsAsyncResult : ScheduleActionItemAsyncResult
- {
- Message message;
- XmlDictionaryWriter writer;
- public OnWriteBodyContentsAsyncResult(XmlDictionaryWriter writer, Message message, AsyncCallback callback, object state)
- : base(callback, state)
- {
- Fx.Assert(message != null, "message should never be null");
- this.message = message;
- this.writer = writer;
- Schedule();
- }
- protected override void OnDoWork()
- {
- this.message.OnWriteBodyContents(this.writer);
- }
- }
- class OnWriteMessageAsyncResult : ScheduleActionItemAsyncResult
- {
- Message message;
- XmlDictionaryWriter writer;
- public OnWriteMessageAsyncResult(XmlDictionaryWriter writer, Message message, AsyncCallback callback, object state)
- : base(callback, state)
- {
- Fx.Assert(message != null, "message should never be null");
- this.message = message;
- this.writer = writer;
- Schedule();
- }
- protected override void OnDoWork()
- {
- this.message.OnWriteMessage(this.writer);
- }
- }
- }
- class EmptyBodyWriter : BodyWriter
- {
- static EmptyBodyWriter value;
- EmptyBodyWriter()
- : base(true)
- {
- }
- public static EmptyBodyWriter Value
- {
- get
- {
- if (value == null)
- value = new EmptyBodyWriter();
- return value;
- }
- }
- internal override bool IsEmpty
- {
- get { return true; }
- }
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- }
- }
- class FaultBodyWriter : BodyWriter
- {
- MessageFault fault;
- EnvelopeVersion version;
- public FaultBodyWriter(MessageFault fault, EnvelopeVersion version)
- : base(true)
- {
- this.fault = fault;
- this.version = version;
- }
- internal override bool IsFault
- {
- get { return true; }
- }
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- fault.WriteTo(writer, version);
- }
- }
- class XmlObjectSerializerBodyWriter : BodyWriter
- {
- object body;
- XmlObjectSerializer serializer;
- public XmlObjectSerializerBodyWriter(object body, XmlObjectSerializer serializer)
- : base(true)
- {
- this.body = body;
- this.serializer = serializer;
- }
- object ThisLock
- {
- get { return this; }
- }
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- lock (ThisLock)
- {
- serializer.WriteObject(writer, body);
- }
- }
- }
- class XmlReaderBodyWriter : BodyWriter
- {
- XmlDictionaryReader reader;
- bool isFault;
- public XmlReaderBodyWriter(XmlDictionaryReader reader, EnvelopeVersion version)
- : base(false)
- {
- this.reader = reader;
- if (reader.MoveToContent() != XmlNodeType.Element)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidReaderPositionOnCreateMessage), "reader"));
- this.isFault = Message.IsFaultStartElement(reader, version);
- }
- internal override bool IsFault
- {
- get
- {
- return this.isFault;
- }
- }
- protected override BodyWriter OnCreateBufferedCopy(int maxBufferSize)
- {
- return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
- }
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- using (reader)
- {
- XmlNodeType type = reader.MoveToContent();
- while (!reader.EOF && type != XmlNodeType.EndElement)
- {
- if (type != XmlNodeType.Element)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidReaderPositionOnCreateMessage), "reader"));
- writer.WriteNode(reader, false);
- type = reader.MoveToContent();
- }
- }
- }
- }
- class BodyWriterMessage : Message
- {
- MessageProperties properties;
- MessageHeaders headers;
- BodyWriter bodyWriter;
- BodyWriterMessage(BodyWriter bodyWriter)
- {
- this.bodyWriter = bodyWriter;
- }
- public BodyWriterMessage(MessageVersion version, string action, BodyWriter bodyWriter)
- : this(bodyWriter)
- {
- this.headers = new MessageHeaders(version);
- this.headers.Action = action;
- }
- public BodyWriterMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter bodyWriter)
- : this(bodyWriter)
- {
- this.headers = new MessageHeaders(version);
- this.headers.SetActionHeader(actionHeader);
- }
- public BodyWriterMessage(MessageHeaders headers, KeyValuePair<string, object>[] properties, BodyWriter bodyWriter)
- : this(bodyWriter)
- {
- this.headers = new MessageHeaders(headers);
- this.properties = new MessageProperties(properties);
- }
- public override bool IsFault
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- return bodyWriter.IsFault;
- }
- }
- public override bool IsEmpty
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- return bodyWriter.IsEmpty;
- }
- }
- public override MessageHeaders Headers
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- return headers;
- }
- }
- public override MessageProperties Properties
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- if (properties == null)
- properties = new MessageProperties();
- return properties;
- }
- }
- public override MessageVersion Version
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- return headers.MessageVersion;
- }
- }
- protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
- {
- BodyWriter bufferedBodyWriter;
- if (bodyWriter.IsBuffered)
- {
- bufferedBodyWriter = bodyWriter;
- }
- else
- {
- bufferedBodyWriter = bodyWriter.CreateBufferedCopy(maxBufferSize);
- }
- KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
- ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
- return new BodyWriterMessageBuffer(headers, properties, bufferedBodyWriter);
- }
- protected override void OnClose()
- {
- Exception ex = null;
- try
- {
- base.OnClose();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- ex = e;
- }
- try
- {
- if (properties != null)
- properties.Dispose();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- if (ex == null)
- ex = e;
- }
- if (ex != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
- bodyWriter = null;
- }
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- bodyWriter.WriteBodyContents(writer);
- }
- protected override IAsyncResult OnBeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
- {
- WriteMessagePreamble(writer);
- return new OnWriteMessageAsyncResult(writer, this, callback, state);
- }
- protected override void OnEndWriteMessage(IAsyncResult result)
- {
- OnWriteMessageAsyncResult.End(result);
- }
- protected override IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
- {
- return bodyWriter.BeginWriteBodyContents(writer, callback, state);
- }
- protected override void OnEndWriteBodyContents(IAsyncResult result)
- {
- bodyWriter.EndWriteBodyContents(result);
- }
- protected override void OnBodyToString(XmlDictionaryWriter writer)
- {
- if (bodyWriter.IsBuffered)
- {
- bodyWriter.WriteBodyContents(writer);
- }
- else
- {
- writer.WriteString(SR.GetString(SR.MessageBodyIsStream));
- }
- }
- protected internal BodyWriter BodyWriter
- {
- get
- {
- return bodyWriter;
- }
- }
- class OnWriteMessageAsyncResult : AsyncResult
- {
- BodyWriterMessage message;
- XmlDictionaryWriter writer;
- public OnWriteMessageAsyncResult(XmlDictionaryWriter writer, BodyWriterMessage message, AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.message = message;
- this.writer = writer;
- if (HandleWriteBodyContents(null))
- {
- this.Complete(true);
- }
- }
- bool HandleWriteBodyContents(IAsyncResult result)
- {
- if (result == null)
- {
- result = this.message.OnBeginWriteBodyContents(this.writer, PrepareAsyncCompletion(HandleWriteBodyContents), this);
- if (!result.CompletedSynchronously)
- {
- return false;
- }
- }
- this.message.OnEndWriteBodyContents(result);
- this.message.WriteMessagePostamble(this.writer);
- return true;
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<OnWriteMessageAsyncResult>(result);
- }
- }
- }
- abstract class ReceivedMessage : Message
- {
- bool isFault;
- bool isEmpty;
- public override bool IsEmpty
- {
- get { return isEmpty; }
- }
- public override bool IsFault
- {
- get { return isFault; }
- }
- protected static bool HasHeaderElement(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
- {
- return reader.IsStartElement(XD.MessageDictionary.Header, envelopeVersion.DictionaryNamespace);
- }
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- if (!isEmpty)
- {
- using (XmlDictionaryReader bodyReader = OnGetReaderAtBodyContents())
- {
- if (bodyReader.ReadState == ReadState.Error || bodyReader.ReadState == ReadState.Closed)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageBodyReaderInvalidReadState, bodyReader.ReadState.ToString())));
- while (bodyReader.NodeType != XmlNodeType.EndElement && !bodyReader.EOF)
- {
- writer.WriteNode(bodyReader, false);
- }
- this.ReadFromBodyContentsToEnd(bodyReader);
- }
- }
- }
- protected bool ReadStartBody(XmlDictionaryReader reader)
- {
- return Message.ReadStartBody(reader, this.Version.Envelope, out this.isFault, out this.isEmpty);
- }
- protected static EnvelopeVersion ReadStartEnvelope(XmlDictionaryReader reader)
- {
- EnvelopeVersion envelopeVersion;
- if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message12Dictionary.Namespace))
- envelopeVersion = EnvelopeVersion.Soap12;
- else if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message11Dictionary.Namespace))
- envelopeVersion = EnvelopeVersion.Soap11;
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageVersionUnknown)));
- if (reader.IsEmptyElement)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageBodyMissing)));
- reader.Read();
- return envelopeVersion;
- }
- protected static void VerifyStartBody(XmlDictionaryReader reader, EnvelopeVersion version)
- {
- if (!reader.IsStartElement(XD.MessageDictionary.Body, version.DictionaryNamespace))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageBodyMissing)));
- }
- }
- sealed class StreamedMessage : ReceivedMessage
- {
- MessageHeaders headers;
- XmlAttributeHolder[] envelopeAttributes;
- XmlAttributeHolder[] headerAttributes;
- XmlAttributeHolder[] bodyAttributes;
- string envelopePrefix;
- string headerPrefix;
- string bodyPrefix;
- MessageProperties properties;
- XmlDictionaryReader reader;
- XmlDictionaryReaderQuotas quotas;
- public StreamedMessage(XmlDictionaryReader reader, int maxSizeOfHeaders, MessageVersion desiredVersion)
- {
- properties = new MessageProperties();
- if (reader.NodeType != XmlNodeType.Element)
- reader.MoveToContent();
- if (desiredVersion.Envelope == EnvelopeVersion.None)
- {
- this.reader = reader;
- this.headerAttributes = XmlAttributeHolder.emptyArray;
- this.headers = new MessageHeaders(desiredVersion);
- }
- else
- {
- envelopeAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
- envelopePrefix = reader.Prefix;
- EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
- if (desiredVersion.Envelope != envelopeVersion)
- {
- Exception versionMismatchException = new ArgumentException(SR.GetString(SR.EncoderEnvelopeVersionMismatch, envelopeVersion, desiredVersion.Envelope), "reader");
- throw TraceUtility.ThrowHelperError(
- new CommunicationException(versionMismatchException.Message, versionMismatchException),
- this);
- }
- if (HasHeaderElement(reader, envelopeVersion))
- {
- headerPrefix = reader.Prefix;
- headerAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
- headers = new MessageHeaders(desiredVersion, reader, envelopeAttributes, headerAttributes, ref maxSizeOfHeaders);
- }
- else
- {
- headerAttributes = XmlAttributeHolder.emptyArray;
- headers = new MessageHeaders(desiredVersion);
- }
- if (reader.NodeType != XmlNodeType.Element)
- reader.MoveToContent();
- bodyPrefix = reader.Prefix;
- VerifyStartBody(reader, envelopeVersion);
- bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
- if (ReadStartBody(reader))
- {
- this.reader = reader;
- }
- else
- {
- this.quotas = new XmlDictionaryReaderQuotas();
- reader.Quotas.CopyTo(this.quotas);
- reader.Close();
- }
- }
- }
- public override MessageHeaders Headers
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- return headers;
- }
- }
- public override MessageVersion Version
- {
- get
- {
- return headers.MessageVersion;
- }
- }
- public override MessageProperties Properties
- {
- get
- {
- return properties;
- }
- }
- protected override void OnBodyToString(XmlDictionaryWriter writer)
- {
- writer.WriteString(SR.GetString(SR.MessageBodyIsStream));
- }
- protected override void OnClose()
- {
- Exception ex = null;
- try
- {
- base.OnClose();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- ex = e;
- }
- try
- {
- properties.Dispose();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- if (ex == null)
- ex = e;
- }
- try
- {
- if (reader != null)
- {
- reader.Close();
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- if (ex == null)
- ex = e;
- }
- if (ex != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
- }
- protected override XmlDictionaryReader OnGetReaderAtBodyContents()
- {
- XmlDictionaryReader reader = this.reader;
- this.reader = null;
- return reader;
- }
- protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
- {
- if (this.reader != null)
- return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
- return OnCreateBufferedCopy(maxBufferSize, this.quotas);
- }
- protected override void OnWriteStartBody(XmlDictionaryWriter writer)
- {
- writer.WriteStartElement(bodyPrefix, MessageStrings.Body, Version.Envelope.Namespace);
- XmlAttributeHolder.WriteAttributes(bodyAttributes, writer);
- }
- protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
- {
- EnvelopeVersion envelopeVersion = Version.Envelope;
- writer.WriteStartElement(envelopePrefix, MessageStrings.Envelope, envelopeVersion.Namespace);
- XmlAttributeHolder.WriteAttributes(envelopeAttributes, writer);
- }
- protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
- {
- EnvelopeVersion envelopeVersion = Version.Envelope;
- writer.WriteStartElement(headerPrefix, MessageStrings.Header, envelopeVersion.Namespace);
- XmlAttributeHolder.WriteAttributes(headerAttributes, writer);
- }
- protected override string OnGetBodyAttribute(string localName, string ns)
- {
- return XmlAttributeHolder.GetAttribute(bodyAttributes, localName, ns);
- }
- }
- interface IBufferedMessageData
- {
- MessageEncoder MessageEncoder { get; }
- ArraySegment<byte> Buffer { get; }
- XmlDictionaryReaderQuotas Quotas { get; }
- void Close();
- void EnableMultipleUsers();
- XmlDictionaryReader GetMessageReader();
- void Open();
- void ReturnMessageState(RecycledMessageState messageState);
- RecycledMessageState TakeMessageState();
- }
- sealed class BufferedMessage : ReceivedMessage
- {
- MessageHeaders headers;
- MessageProperties properties;
- IBufferedMessageData messageData;
- RecycledMessageState recycledMessageState;
- XmlDictionaryReader reader;
- XmlAttributeHolder[] bodyAttributes;
- public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState)
- : this(messageData, recycledMessageState, null, false)
- {
- }
- public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, bool[] understoodHeaders, bool understoodHeadersModified)
- {
- bool throwing = true;
- try
- {
- this.recycledMessageState = recycledMessageState;
- this.messageData = messageData;
- properties = recycledMessageState.TakeProperties();
- if (properties == null)
- this.properties = new MessageProperties();
- XmlDictionaryReader reader = messageData.GetMessageReader();
- MessageVersion desiredVersion = messageData.MessageEncoder.MessageVersion;
- if (desiredVersion.Envelope == EnvelopeVersion.None)
- {
- this.reader = reader;
- this.headers = new MessageHeaders(desiredVersion);
- }
- else
- {
- EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
- if (desiredVersion.Envelope != envelopeVersion)
- {
- Exception versionMismatchException = new ArgumentException(SR.GetString(SR.EncoderEnvelopeVersionMismatch, envelopeVersion, desiredVersion.Envelope), "reader");
- throw TraceUtility.ThrowHelperError(
- new CommunicationException(versionMismatchException.Message, versionMismatchException),
- this);
- }
- if (HasHeaderElement(reader, envelopeVersion))
- {
- headers = recycledMessageState.TakeHeaders();
- if (headers == null)
- {
- headers = new MessageHeaders(desiredVersion, reader, messageData, recycledMessageState, understoodHeaders, understoodHeadersModified);
- }
- else
- {
- headers.Init(desiredVersion, reader, messageData, recycledMessageState, understoodHeaders, understoodHeadersModified);
- }
- }
- else
- {
- headers = new MessageHeaders(desiredVersion);
- }
- VerifyStartBody(reader, envelopeVersion);
- int maxSizeOfAttributes = int.MaxValue;
- bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfAttributes);
- if (maxSizeOfAttributes < int.MaxValue - 4096)
- bodyAttributes = null;
- if (ReadStartBody(reader))
- {
- this.reader = reader;
- }
- else
- {
- reader.Close();
- }
- }
- throwing = false;
- }
- finally
- {
- if (throwing && MessageLogger.LoggingEnabled)
- {
- MessageLogger.LogMessage(messageData.Buffer, MessageLoggingSource.Malformed);
- }
- }
- }
- public override MessageHeaders Headers
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- return headers;
- }
- }
- internal IBufferedMessageData MessageData
- {
- get
- {
- return messageData;
- }
- }
- public override MessageProperties Properties
- {
- get
- {
- if (IsDisposed)
- #pragma warning suppress 56503 // [....], Invalid State after dispose
- throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
- return properties;
- }
- }
- internal override RecycledMessageState RecycledMessageState
- {
- get { return recycledMessageState; }
- }
- public override MessageVersion Version
- {
- get
- {
- return headers.MessageVersion;
- }
- }
- protected override XmlDictionaryReader OnGetReaderAtBodyContents()
- {
- XmlDictionaryReader reader = this.reader;
- this.reader = null;
- return reader;
- }
- internal override XmlDictionaryReader GetReaderAtHeader()
- {
- if (!headers.ContainsOnlyBufferedMessageHeaders)
- return base.GetReaderAtHeader();
- XmlDictionaryReader reader = messageData.GetMessageReader();
- if (reader.NodeType != XmlNodeType.Element)
- reader.MoveToContent();
- reader.Read();
- if (HasHeaderElement(reader, headers.MessageVersion.Envelope))
- return reader;
- return base.GetReaderAtHeader();
- }
- public XmlDictionaryReader GetBufferedReaderAtBody()
- {
- XmlDictionaryReader reader = messageData.GetMessageReader();
- if (reader.NodeType != XmlNodeType.Element)
- reader.MoveToContent();
- if (this.Version.Envelope != EnvelopeVersion.None)
- {
- reader.Read();
- if (HasHeaderElement(reader, headers.MessageVersion.Envelope))
- reader.Skip();
- if (reader.NodeType != XmlNodeType.Element)
- reader.MoveToContent();
- }
- return reader;
- }
- public XmlDictionaryReader GetMessageReader()
- {
- return messageData.GetMessageReader();
- }
- protected override void OnBodyToString(XmlDictionaryWriter writer)
- {
- using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
- {
- if (this.Version == MessageVersion.None)
- {
- writer.WriteNode(reader, false);
- }
- else
- {
- if (!reader.IsEmptyElement)
- {
- reader.ReadStartElement();
- while (reader.NodeType != XmlNodeType.EndElement)
- writer.WriteNode(reader, false);
- }
- }
- }
- }
- protected override void OnClose()
- {
- Exception ex = null;
- try
- {
- base.OnClose();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- ex = e;
- }
- try
- {
- properties.Dispose();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- if (ex == null)
- ex = e;
- }
- try
- {
- if (reader != null)
- {
- reader.Close();
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- if (ex == null)
- ex = e;
- }
- try
- {
- recycledMessageState.ReturnHeaders(headers);
- recycledMessageState.ReturnProperties(properties);
- messageData.ReturnMessageState(recycledMessageState);
- recycledMessageState = null;
- messageData.Close();
- messageData = null;
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- if (ex == null)
- ex = e;
- }
- if (ex != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
- }
- protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
- {
- using (XmlDictionaryReader reader = GetMessageReader())
- {
- reader.MoveToContent();
- EnvelopeVersion envelopeVersion = Version.Envelope;
- writer.WriteStartElement(reader.Prefix, MessageStrings.Envelope, envelopeVersion.Namespace);
- writer.WriteAttributes(reader, false);
- }
- }
- protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
- {
- using (XmlDictionaryReader reader = GetMessageReader())
- {
- reader.MoveToContent();
- EnvelopeVersion envelopeVersion = Version.Envelope;
- reader.Read();
- if (HasHeaderElement(reader, envelopeVersion))
- {
- writer.WriteStartElement(reader.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
- writer.WriteAttributes(reader, false);
- }
- else
- {
- writer.WriteStartElement(MessageStrings.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
- }
- }
- }
- protected override void OnWriteStartBody(XmlDictionaryWriter writer)
- {
- using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
- {
- writer.WriteStartElement(reader.Prefix, MessageStrings.Body, Version.Envelope.Namespace);
- writer.WriteAttributes(reader, false);
- }
- }
- protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
- {
- if (headers.ContainsOnlyBufferedMessageHeaders)
- {
- KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
- ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
- messageData.EnableMultipleUsers();
- bool[] understoodHeaders = null;
- if (headers.HasMustUnderstandBeenModified)
- {
- understoodHeaders = new bool[headers.Count];
- for (int i = 0; i < headers.Count; i++)
- {
- understoodHeaders[i] = headers.IsUnderstood(i);
- }
- }
- return new BufferedMessageBuffer(messageData, properties, understoodHeaders, headers.HasMustUnderstandBeenModified);
- }
- else
- {
- if (this.reader != null)
- return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
- return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max);
- }
- }
- protected override string OnGetBodyAttribute(string localName, string ns)
- {
- if (this.bodyAttributes != null)
- return XmlAttributeHolder.GetAttribute(this.bodyAttributes, localName, ns);
- using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
- {
- return reader.GetAttribute(localName, ns);
- }
- }
- }
- struct XmlAttributeHolder
- {
- string prefix;
- string ns;
- string localName;
- string value;
- public static XmlAttributeHolder[] emptyArray = new XmlAttributeHolder[0];
- public XmlAttributeHolder(string prefix, string localName, string ns, string value)
- {
- this.prefix = prefix;
- this.localName = localName;
- this.ns = ns;
- this.value = value;
- }
- public string Prefix
- {
- get { return prefix; }
- }
- public string NamespaceUri
- {
- get { return ns; }
- }
- public string LocalName
- {
- get { return localName; }
- }
- public string Value
- {
- get { return value; }
- }
- public void WriteTo(XmlWriter writer)
- {
- writer.WriteStartAttribute(prefix, localName, ns);
- writer.WriteString(value);
- writer.WriteEndAttribute();
- }
- public static void WriteAttributes(XmlAttributeHolder[] attributes, XmlWriter writer)
- {
- for (int i = 0; i < attributes.Length; i++)
- attributes[i].WriteTo(writer);
- }
- public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader)
- {
- int maxSizeOfHeaders = int.MaxValue;
- return ReadAttributes(reader, ref maxSizeOfHeaders);
- }
- public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader, ref int maxSizeOfHeaders)
- {
- if (reader.AttributeCount == 0)
- return emptyArray;
- XmlAttributeHolder[] attributes = new XmlAttributeHolder[reader.AttributeCount];
- reader.MoveToFirstAttribute();
- for (int i = 0; i < attributes.Length; i++)
- {
- string ns = reader.NamespaceURI;
- string localName = reader.LocalName;
- string prefix = reader.Prefix;
- string value = string.Empty;
- while (reader.ReadAttributeValue())
- {
- if (value.Length == 0)
- value = reader.Value;
- else
- value += reader.Value;
- }
- Deduct(prefix, ref maxSizeOfHeaders);
- Deduct(localName, ref maxSizeOfHeaders);
- Deduct(ns, ref maxSizeOfHeaders);
- Deduct(value, ref maxSizeOfHeaders);
- attributes[i] = new XmlAttributeHolder(prefix, localName, ns, value);
- reader.MoveToNextAttribute();
- }
- reader.MoveToElement();
- return attributes;
- }
- static void Deduct(string s, ref int maxSizeOfHeaders)
- {
- int byteCount = s.Length * sizeof(char);
- if (byteCount > maxSizeOfHeaders)
- {
- string message = SR.GetString(SR.XmlBufferQuotaExceeded);
- Exception inner = new QuotaExceededException(message);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(message, inner));
- }
- maxSizeOfHeaders -= byteCount;
- }
- public static string GetAttribute(XmlAttributeHolder[] attributes, string localName, string ns)
- {
- for (int i = 0; i < attributes.Length; i++)
- if (attributes[i].LocalName == localName && attributes[i].NamespaceUri == ns)
- return attributes[i].Value;
- return null;
- }
- }
- class RecycledMessageState
- {
- MessageHeaders recycledHeaders;
- MessageProperties recycledProperties;
- UriCache uriCache;
- HeaderInfoCache headerInfoCache;
- public HeaderInfoCache HeaderInfoCache
- {
- get
- {
- if (headerInfoCache == null)
- {
- headerInfoCache = new HeaderInfoCache();
- }
- return headerInfoCache;
- }
- }
- public UriCache UriCache
- {
- get
- {
- if (uriCache == null)
- uriCache = new UriCache();
- return uriCache;
- }
- }
- public MessageProperties TakeProperties()
- {
- MessageProperties taken = recycledProperties;
- recycledProperties = null;
- return taken;
- }
- public void ReturnProperties(MessageProperties properties)
- {
- if (properties.CanRecycle)
- {
- properties.Recycle();
- this.recycledProperties = properties;
- }
- }
- public MessageHeaders TakeHeaders()
- {
- MessageHeaders taken = recycledHeaders;
- recycledHeaders = null;
- return taken;
- }
- public void ReturnHeaders(MessageHeaders headers)
- {
- if (headers.CanRecycle)
- {
- headers.Recycle(this.HeaderInfoCache);
- this.recycledHeaders = headers;
- }
- }
- }
- class HeaderInfoCache
- {
- const int maxHeaderInfos = 4;
- HeaderInfo[] headerInfos;
- int index;
- public MessageHeaderInfo TakeHeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isRefParam)
- {
- if (this.headerInfos != null)
- {
- int i = this.index;
- for (;;)
- {
- HeaderInfo headerInfo = this.headerInfos[i];
- if (headerInfo != null)
- {
- if (headerInfo.Matches(reader, actor, mustUnderstand, relay, isRefParam))
- {
- this.headerInfos[i] = null;
- this.index = (i + 1) % maxHeaderInfos;
- return headerInfo;
- }
- }
- i = (i + 1) % maxHeaderInfos;
- if (i == this.index)
- {
- break;
- }
- }
- }
- return new HeaderInfo(reader, actor, mustUnderstand, relay, isRefParam);
- }
- public void ReturnHeaderInfo(MessageHeaderInfo headerInfo)
- {
- HeaderInfo headerInfoToReturn = headerInfo as HeaderInfo;
- if (headerInfoToReturn != null)
- {
- if (this.headerInfos == null)
- {
- this.headerInfos = new HeaderInfo[maxHeaderInfos];
- }
- int i = this.index;
- for (;;)
- {
- if (this.headerInfos[i] == null)
- {
- break;
- }
- i = (i + 1) % maxHeaderInfos;
- if (i == this.index)
- {
- break;
- }
- }
- this.headerInfos[i] = headerInfoToReturn;
- this.index = (i + 1) % maxHeaderInfos;
- }
- }
- class HeaderInfo : MessageHeaderInfo
- {
- string name;
- string ns;
- string actor;
- bool isReferenceParameter;
- bool mustUnderstand;
- bool relay;
- public HeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isReferenceParameter)
- {
- this.actor = actor;
- this.mustUnderstand = mustUnderstand;
- this.relay = relay;
- this.isReferenceParameter = isReferenceParameter;
- reader.GetNonAtomizedNames(out name, out ns);
- }
- public override string Name
- {
- get { return name; }
- }
- public override string Namespace
- {
- get { return ns; }
- }
- public override bool IsReferenceParameter
- {
- get { return isReferenceParameter; }
- }
- public override string Actor
- {
- get { return actor; }
- }
- public override bool MustUnderstand
- {
- get { return mustUnderstand; }
- }
- public override bool Relay
- {
- get { return relay; }
- }
- public bool Matches(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isRefParam)
- {
- return reader.IsStartElement(this.name, this.ns) &&
- this.actor == actor && this.mustUnderstand == mustUnderstand && this.relay == relay && this.isReferenceParameter == isRefParam;
- }
- }
- }
- class UriCache
- {
- const int MaxKeyLength = 128;
- const int MaxEntries = 8;
- Entry[] entries;
- int count;
- public UriCache()
- {
- entries = new Entry[MaxEntries];
- }
- public Uri CreateUri(string uriString)
- {
- Uri uri = Get(uriString);
- if (uri == null)
- {
- uri = new Uri(uriString);
- Set(uriString, uri);
- }
- return uri;
- }
- Uri Get(string key)
- {
- if (key.Length > MaxKeyLength)
- return null;
- for (int i = count - 1; i >= 0; i--)
- if (entries[i].Key == key)
- return entries[i].Value;
- return null;
- }
- void Set(string key, Uri value)
- {
- if (key.Length > MaxKeyLength)
- return;
- if (count < entries.Length)
- {
- entries[count++] = new Entry(key, value);
- }
- else
- {
- Array.Copy(entries, 1, entries, 0, entries.Length - 1);
- entries[count - 1] = new Entry(key, value);
- }
- }
- struct Entry
- {
- string key;
- Uri value;
- public Entry(string key, Uri value)
- {
- this.key = key;
- this.value = value;
- }
- public string Key
- {
- get { return key; }
- }
- public Uri Value
- {
- get { return value; }
- }
- }
- }
- }
|