2010-03-24 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Channels / MessageImpl.cs
blobb3ca10f349156300dbdca0ccb64c10729f4cf900
1 //
2 // MessageImpl.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006 Novell, Inc. http://www.novell.com
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
28 using System;
29 using System.Runtime.Serialization;
30 using System.Xml;
31 using System.IO;
33 namespace System.ServiceModel.Channels
35 internal class XmlReaderMessage : Message
37 MessageVersion version;
38 XmlDictionaryReader reader;
39 MessageHeaders headers;
40 MessageProperties properties = new MessageProperties ();
41 bool is_empty, is_fault, body_started, body_consumed;
42 int max_headers;
44 public XmlReaderMessage (MessageVersion version, XmlDictionaryReader reader, int maxSizeOfHeaders)
46 this.version = version;
47 this.reader = reader;
48 this.max_headers = maxSizeOfHeaders;
50 ReadEnvelopeStart ();
53 public override MessageHeaders Headers {
54 get {
55 if (headers == null)
56 ReadHeaders ();
57 return headers;
61 public override bool IsEmpty {
62 get {
63 if (!body_started)
64 ReadBodyStart ();
65 return is_empty;
69 public override bool IsFault {
70 get {
71 if (!body_started)
72 ReadBodyStart ();
73 return is_fault;
77 public override MessageProperties Properties {
78 get { return properties; }
81 public override MessageVersion Version {
82 get { return version; }
85 protected override string OnGetBodyAttribute (
86 string localName, string ns)
88 if (headers == null)
89 ReadHeaders ();
90 return reader.GetAttribute (localName, ns);
93 protected override XmlDictionaryReader OnGetReaderAtBodyContents ()
95 if (reader.ReadState == ReadState.Closed)
96 return reader; // silly, but that's what our test expects.
97 if (body_consumed)
98 throw new InvalidOperationException ("The message body XmlReader is already consumed.");
99 if (!body_started)
100 ReadBodyStart ();
101 if (is_empty)
102 throw new InvalidOperationException ("The message body is empty.");
103 body_consumed = true;
104 return reader;
107 protected override void OnWriteBodyContents (
108 XmlDictionaryWriter writer)
110 XmlDictionaryReader reader = GetReaderAtBodyContents ();
111 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement)
112 writer.WriteNode (reader, false);
115 static readonly char [] whitespaceChars = new char [] {' ', '\t', '\r', '\n'};
117 void ReadEnvelopeStart ()
119 reader.MoveToContent ();
120 if (reader.IsEmptyElement)
121 throw new ArgumentException ("Missing message content XML.");
122 reader.ReadStartElement ("Envelope", Version.Envelope.Namespace);
124 // SOAP Header
125 reader.MoveToContent ();
128 void ReadHeaders ()
130 if (headers != null)
131 throw new InvalidOperationException ("XmlReader at headers is already consumed.");
133 string envNS = Version.Envelope.Namespace;
135 headers = new MessageHeaders (version, max_headers);
136 if (reader.LocalName != "Header" || reader.NamespaceURI != envNS)
137 return;
139 bool isEmptyHeader = reader.IsEmptyElement;
140 reader.ReadStartElement ("Header", envNS);
141 reader.MoveToContent ();
142 if (isEmptyHeader)
143 return;
145 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement) {
146 if (reader.NodeType == XmlNodeType.Element)
147 headers.Add (new MessageHeader.RawMessageHeader (reader, envNS));
148 else
149 reader.Skip ();
150 // FIXME: handle UnderstoodHeaders as well.
151 reader.MoveToContent ();
153 reader.ReadEndElement ();
154 reader.MoveToContent ();
157 void ReadBodyStart ()
159 // read headers in advance.
160 if (headers == null)
161 ReadHeaders ();
163 // SOAP Body
164 body_started = true;
165 is_empty = reader.IsEmptyElement;
166 if (reader.MoveToAttribute ("Id", Constants.WsuNamespace)) {
167 BodyId = reader.Value;
168 reader.MoveToElement ();
170 reader.ReadStartElement ("Body", Version.Envelope.Namespace);
171 if (reader.NodeType == XmlNodeType.EndElement) {
172 is_empty = true;
173 reader.Read ();
174 } else {
175 reader.MoveToContent ();
176 if (reader.NodeType == XmlNodeType.Element &&
177 reader.LocalName == "Fault" &&
178 reader.NamespaceURI == Version.Envelope.Namespace)
179 is_fault = true;
184 internal abstract class MessageImplBase : Message
186 MessageHeaders headers;
187 MessageProperties properties = new MessageProperties ();
189 public MessageImplBase (MessageVersion version, string action)
191 headers = new MessageHeaders (version);
192 if (action != null)
193 headers.Action = action;
196 public override MessageHeaders Headers {
197 get { return headers; }
200 public override MessageProperties Properties {
201 get { return properties; }
204 public override MessageVersion Version {
205 get { return Headers.MessageVersion; }
209 internal class EmptyMessage : MessageImplBase
211 public EmptyMessage (MessageVersion version, string action)
212 : base (version, action)
216 public override bool IsEmpty {
217 get { return true; }
220 protected override void OnWriteBodyContents (
221 XmlDictionaryWriter writer)
225 protected override MessageBuffer OnCreateBufferedCopy (
226 int maxBufferSize)
228 return new DefaultMessageBuffer (Headers, Properties);
232 internal class SimpleMessage : MessageImplBase
234 BodyWriter body;
235 bool is_fault;
237 public SimpleMessage (MessageVersion version,
238 string action, BodyWriter body, bool isFault)
239 : base (version, action)
241 this.body = body;
242 this.is_fault = isFault;
245 public override bool IsEmpty {
246 get { return false; }
249 public override bool IsFault {
250 get { return is_fault; }
253 protected override void OnWriteBodyContents (
254 XmlDictionaryWriter writer)
256 body.WriteBodyContents (writer);
259 protected override MessageBuffer OnCreateBufferedCopy (
260 int maxBufferSize)
262 var headers = new MessageHeaders (Headers);
263 var props = new MessageProperties (Properties);
264 return new DefaultMessageBuffer (maxBufferSize, headers, props, body.CreateBufferedCopy (maxBufferSize), false);