5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2006 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Runtime.Serialization;
33 namespace System.ServiceModel.Channels
35 // Apparently Microsoft should have split Message class into
36 // two diffferent public classes such as IncomingMessage and
38 internal class XmlReaderMessage : Message
40 MessageVersion version;
41 XmlDictionaryReader reader;
42 MessageHeaders headers;
43 MessageProperties properties = new MessageProperties ();
44 bool is_empty, is_fault, body_started, body_consumed;
49 public XmlReaderMessage (MessageVersion version, XmlDictionaryReader reader, int maxSizeOfHeaders)
51 this.version = version;
53 this.max_headers = maxSizeOfHeaders;
56 // Headers and IsEmpty are consumed at this stage.
57 // Body content is not.
60 StringWriter sw = new StringWriter ();
61 using (XmlDictionaryWriter bodyXml = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (sw))) {
62 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement)
63 bodyXml.WriteNode (reader, false);
65 this.body = sw.ToString ();
68 public override MessageHeaders Headers {
76 public override bool IsEmpty {
84 public override bool IsFault {
92 public override MessageProperties Properties {
93 get { return properties; }
96 public override MessageVersion Version {
97 get { return version; }
100 protected override string OnGetBodyAttribute (
101 string localName, string ns)
105 return reader.GetAttribute (localName, ns);
108 protected override XmlDictionaryReader OnGetReaderAtBodyContents ()
110 XmlDictionaryReader newReader = XmlDictionaryReader.CreateDictionaryReader (XmlReader.Create (new StringReader (this.body)));
111 newReader.MoveToContent();
115 protected override void OnWriteBodyContents (
116 XmlDictionaryWriter writer)
118 XmlDictionaryReader reader = GetReaderAtBodyContents ();
119 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement)
120 writer.WriteNode (reader, false);
123 static readonly char [] whitespaceChars = new char [] {' ', '\t', '\r', '\n'};
125 void ReadEnvelopeStart ()
127 reader.MoveToContent ();
128 if (reader.IsEmptyElement)
129 throw new ArgumentException ("Missing message content XML.");
130 reader.ReadStartElement ("Envelope", Version.Envelope.Namespace);
133 reader.MoveToContent ();
139 throw new InvalidOperationException ("XmlReader at headers is already consumed.");
141 string envNS = Version.Envelope.Namespace;
143 headers = new MessageHeaders (version, max_headers);
144 if (reader.LocalName != "Header" || reader.NamespaceURI != envNS)
147 bool isEmptyHeader = reader.IsEmptyElement;
148 reader.ReadStartElement ("Header", envNS);
149 reader.MoveToContent ();
153 XmlDocument doc = null;
154 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement) {
156 doc = new XmlDocument ();
157 XmlElement el = doc.ReadNode (reader) as XmlElement;
159 headers.Add (MessageHeader.CreateInternalHeader (el, envNS));
160 // FIXME: handle UnderstoodHeaders as well.
161 reader.MoveToContent ();
163 reader.ReadEndElement ();
164 reader.MoveToContent ();
167 void ReadBodyStart ()
169 // read headers in advance.
175 is_empty = reader.IsEmptyElement;
176 if (reader.MoveToAttribute ("Id", Constants.WsuNamespace)) {
177 BodyId = reader.Value;
178 reader.MoveToElement ();
180 reader.ReadStartElement ("Body", Version.Envelope.Namespace);
181 if (reader.NodeType == XmlNodeType.EndElement) {
185 reader.MoveToContent ();
186 if (reader.NodeType == XmlNodeType.Element &&
187 reader.LocalName == "Fault" &&
188 reader.NamespaceURI == Version.Envelope.Namespace)
194 internal abstract class MessageImplBase : Message
196 MessageHeaders headers;
197 MessageProperties properties = new MessageProperties ();
199 public MessageImplBase (MessageVersion version, string action)
201 headers = new MessageHeaders (version);
203 headers.Action = action;
206 public override MessageHeaders Headers {
207 get { return headers; }
210 public override MessageProperties Properties {
211 get { return properties; }
214 public override MessageVersion Version {
215 get { return Headers.MessageVersion; }
219 internal class EmptyMessage : MessageImplBase
221 public EmptyMessage (MessageVersion version, string action)
222 : base (version, action)
226 public override bool IsEmpty {
230 protected override void OnWriteBodyContents (
231 XmlDictionaryWriter writer)
235 protected override MessageBuffer OnCreateBufferedCopy (
238 return new DefaultMessageBuffer (Headers, Properties);
242 internal class SimpleMessage : MessageImplBase
247 public SimpleMessage (MessageVersion version,
248 string action, BodyWriter body, bool isFault)
249 : base (version, action)
252 this.is_fault = isFault;
255 public override bool IsEmpty {
256 get { return false; }
259 public override bool IsFault {
260 get { return is_fault; }
263 protected override void OnWriteBodyContents (
264 XmlDictionaryWriter writer)
266 body.WriteBodyContents (writer);