2010-04-15 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Channels / MessageImpl.cs
blobb4c341d029722394abe3282365321c117fbe73ff
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 ReadBodyStart ();
64 return is_empty;
68 public override bool IsFault {
69 get {
70 ReadBodyStart ();
71 return is_fault;
75 public override MessageProperties Properties {
76 get { return properties; }
79 public override MessageVersion Version {
80 get { return version; }
83 protected override MessageBuffer OnCreateBufferedCopy (
84 int maxBufferSize)
86 ReadBodyStart ();
87 var headers = new MessageHeaders (Headers);
88 var props = new MessageProperties (Properties);
89 return new DefaultMessageBuffer (maxBufferSize, headers, props, new XmlReaderBodyWriter (reader), IsFault);
92 protected override string OnGetBodyAttribute (
93 string localName, string ns)
95 if (headers == null)
96 ReadHeaders ();
97 return reader.GetAttribute (localName, ns);
100 protected override XmlDictionaryReader OnGetReaderAtBodyContents ()
102 if (reader.ReadState == ReadState.Closed)
103 return reader; // silly, but that's what our test expects.
104 if (body_consumed)
105 throw new InvalidOperationException ("The message body XmlReader is already consumed.");
106 ReadBodyStart ();
107 if (is_empty)
108 throw new InvalidOperationException ("The message body is empty.");
109 body_consumed = true;
110 return reader;
113 protected override void OnWriteBodyContents (
114 XmlDictionaryWriter writer)
116 XmlDictionaryReader reader = GetReaderAtBodyContents ();
117 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement)
118 writer.WriteNode (reader, false);
121 static readonly char [] whitespaceChars = new char [] {' ', '\t', '\r', '\n'};
123 void ReadEnvelopeStart ()
125 reader.MoveToContent ();
126 if (reader.IsEmptyElement)
127 throw new ArgumentException ("Missing message content XML.");
128 reader.ReadStartElement ("Envelope", Version.Envelope.Namespace);
130 // SOAP Header
131 reader.MoveToContent ();
134 void ReadHeaders ()
136 if (headers != null)
137 throw new InvalidOperationException ("XmlReader at headers is already consumed.");
139 string envNS = Version.Envelope.Namespace;
141 headers = new MessageHeaders (version, max_headers);
142 if (reader.LocalName != "Header" || reader.NamespaceURI != envNS)
143 return;
145 bool isEmptyHeader = reader.IsEmptyElement;
146 reader.ReadStartElement ("Header", envNS);
147 reader.MoveToContent ();
148 if (isEmptyHeader)
149 return;
151 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement) {
152 if (reader.NodeType == XmlNodeType.Element)
153 headers.Add (new MessageHeader.RawMessageHeader (reader, envNS));
154 else
155 reader.Skip ();
156 // FIXME: handle UnderstoodHeaders as well.
157 reader.MoveToContent ();
159 reader.ReadEndElement ();
160 reader.MoveToContent ();
163 void ReadBodyStart ()
165 if (body_started)
166 return;
168 // read headers in advance.
169 if (headers == null)
170 ReadHeaders ();
172 // SOAP Body
173 body_started = true;
174 is_empty = reader.IsEmptyElement;
175 if (reader.MoveToAttribute ("Id", Constants.WsuNamespace)) {
176 BodyId = reader.Value;
177 reader.MoveToElement ();
179 reader.ReadStartElement ("Body", Version.Envelope.Namespace);
180 if (reader.NodeType == XmlNodeType.EndElement) {
181 is_empty = true;
182 reader.Read ();
183 } else {
184 reader.MoveToContent ();
185 if (reader.NodeType == XmlNodeType.Element &&
186 reader.LocalName == "Fault" &&
187 reader.NamespaceURI == Version.Envelope.Namespace)
188 is_fault = true;
193 internal abstract class MessageImplBase : Message
195 MessageHeaders headers;
196 MessageProperties properties = new MessageProperties ();
198 public MessageImplBase (MessageVersion version, string action)
200 headers = new MessageHeaders (version);
201 if (action != null)
202 headers.Action = action;
205 public override MessageHeaders Headers {
206 get { return headers; }
209 public override MessageProperties Properties {
210 get { return properties; }
213 public override MessageVersion Version {
214 get { return Headers.MessageVersion; }
218 internal class EmptyMessage : MessageImplBase
220 public EmptyMessage (MessageVersion version, string action)
221 : base (version, action)
225 public override bool IsEmpty {
226 get { return true; }
229 protected override void OnWriteBodyContents (
230 XmlDictionaryWriter writer)
234 protected override MessageBuffer OnCreateBufferedCopy (
235 int maxBufferSize)
237 return new DefaultMessageBuffer (Headers, Properties);
241 internal class SimpleMessage : MessageImplBase
243 BodyWriter body;
244 bool is_fault;
246 public SimpleMessage (MessageVersion version,
247 string action, BodyWriter body, bool isFault)
248 : base (version, action)
250 this.body = body;
251 this.is_fault = isFault;
254 public override bool IsEmpty {
255 get { return false; }
258 public override bool IsFault {
259 get { return is_fault; }
262 protected override void OnWriteBodyContents (
263 XmlDictionaryWriter writer)
265 body.WriteBodyContents (writer);
268 protected override MessageBuffer OnCreateBufferedCopy (
269 int maxBufferSize)
271 var headers = new MessageHeaders (Headers);
272 var props = new MessageProperties (Properties);
273 return new DefaultMessageBuffer (maxBufferSize, headers, props, body.CreateBufferedCopy (maxBufferSize), IsFault);