2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Channels / Message.cs
blobf31b1d8595ce0d7bb5e6285e4c14294d411cc2bd
1 //
2 // Message.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005-2006,2010 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.IO;
30 using System.Runtime.Serialization;
31 using System.Xml;
32 using System.Xml.Schema;
33 using Mono.Xml.XPath;
35 namespace System.ServiceModel.Channels
37 public abstract class Message : IDisposable
39 bool disposed;
40 string body_id;
42 protected Message () {
43 State = MessageState.Created;
46 public abstract MessageHeaders Headers { get; }
48 internal string BodyId {
49 get { return body_id; }
50 set { body_id = value; }
53 public virtual bool IsEmpty {
54 get { return false; }
57 public virtual bool IsFault {
58 get { return false; }
61 public abstract MessageProperties Properties { get; }
63 MessageState ___state;
64 public MessageState State {
65 get { return ___state; }
66 private set { ___state = value; }
69 public abstract MessageVersion Version { get; }
71 protected bool IsDisposed {
72 get { return disposed; }
75 public void Close ()
77 if (!disposed)
78 OnClose ();
79 State = MessageState.Closed;
80 disposed = true;
83 public MessageBuffer CreateBufferedCopy (int maxBufferSize)
85 if (State != MessageState.Created)
86 throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
87 try {
88 return OnCreateBufferedCopy (maxBufferSize);
89 } finally {
90 State = MessageState.Copied;
94 void IDisposable.Dispose ()
96 Close ();
99 public T GetBody<T> ()
101 return GetBody<T> (new DataContractSerializer (typeof (T)));
104 public T GetBody<T> (XmlObjectSerializer xmlFormatter)
106 return (T) xmlFormatter.ReadObject (GetReaderAtBodyContents ());
109 public string GetBodyAttribute (string localName, string ns)
111 return OnGetBodyAttribute (localName, ns);
114 public XmlDictionaryReader GetReaderAtBodyContents ()
116 return OnGetReaderAtBodyContents ();
119 public override string ToString ()
121 MessageState tempState = State;
122 try {
124 StringWriter sw = new StringWriter ();
125 XmlWriterSettings settings = new XmlWriterSettings ();
126 settings.Indent = true;
127 settings.OmitXmlDeclaration = true;
128 using (XmlWriter w = XmlWriter.Create (sw, settings)) {
129 WriteMessage (w);
131 return sw.ToString ();
133 finally {
134 State = tempState;
138 void WriteXsiNil (XmlDictionaryWriter writer)
140 var dic = Constants.SoapDictionary;
141 writer.WriteStartElement ("z", dic.Add ("anyType"), dic.Add (Constants.MSSerialization));
142 writer.WriteAttributeString ("i", dic.Add ("nil"), dic.Add ("http://www.w3.org/2001/XMLSchema-instance"), "true");
143 writer.WriteEndElement ();
146 public void WriteBody (XmlDictionaryWriter writer)
148 if (Version.Envelope != EnvelopeVersion.None)
149 WriteStartBody (writer);
150 WriteBodyContents (writer);
151 if (Version.Envelope != EnvelopeVersion.None)
152 writer.WriteEndElement ();
155 public void WriteBody (XmlWriter writer)
157 WriteBody (XmlDictionaryWriter.CreateDictionaryWriter (writer));
160 public void WriteBodyContents (XmlDictionaryWriter writer)
162 if (!IsEmpty)
163 OnWriteBodyContents (writer);
164 else if (Version.Envelope == EnvelopeVersion.None)
165 WriteXsiNil (writer);
166 State = MessageState.Written;
169 public void WriteMessage (XmlDictionaryWriter writer)
171 if (State != MessageState.Created)
172 throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
174 OnWriteMessage (writer);
177 public void WriteMessage (XmlWriter writer)
179 WriteMessage (XmlDictionaryWriter.CreateDictionaryWriter (writer));
182 public void WriteStartBody (XmlDictionaryWriter writer)
184 if (State != MessageState.Created)
185 throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
187 OnWriteStartBody (writer);
190 public void WriteStartBody (XmlWriter writer)
192 WriteStartBody (
193 XmlDictionaryWriter.CreateDictionaryWriter (writer));
196 public void WriteStartEnvelope (XmlDictionaryWriter writer)
198 if (State != MessageState.Created)
199 throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
201 OnWriteStartEnvelope (writer);
204 [MonoTODO]
205 protected virtual void OnBodyToString (
206 XmlDictionaryWriter writer)
208 throw new NotImplementedException ();
211 protected virtual void OnClose ()
215 protected virtual MessageBuffer OnCreateBufferedCopy (
216 int maxBufferSize)
218 var s = new XmlWriterSettings ();
219 s.OmitXmlDeclaration = true;
220 s.ConformanceLevel = ConformanceLevel.Auto;
221 StringWriter sw = new StringWriter ();
222 using (XmlDictionaryWriter w = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (sw, s)))
223 WriteBodyContents (w);
224 var headers = new MessageHeaders (Headers);
225 var props = new MessageProperties (Properties);
226 return new DefaultMessageBuffer (maxBufferSize, headers, props, new XmlReaderBodyWriter (sw.ToString (), maxBufferSize, null), false);
229 protected virtual string OnGetBodyAttribute (
230 string localName, string ns)
232 // other than XmlReaderMessage it cannot return anything
233 return null;
236 protected virtual XmlDictionaryReader OnGetReaderAtBodyContents ()
238 var ws = new XmlWriterSettings ();
239 ws.ConformanceLevel = ConformanceLevel.Auto;
240 StringWriter sw = new StringWriter ();
241 using (XmlDictionaryWriter body = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (sw, ws))) {
242 WriteBodyContents (body);
245 var rs = new XmlReaderSettings ();
246 rs.ConformanceLevel = ConformanceLevel.Auto;
247 return XmlDictionaryReader.CreateDictionaryReader (XmlReader.Create (new StringReader (sw.ToString ()), rs));
250 protected abstract void OnWriteBodyContents (
251 XmlDictionaryWriter writer);
253 protected virtual void OnWriteMessage (
254 XmlDictionaryWriter writer)
256 if (Version.Envelope != EnvelopeVersion.None) {
257 WriteStartEnvelope (writer);
258 if (Headers.Count > 0) {
259 OnWriteStartHeaders (writer);
260 for (int i = 0, count = Headers.Count; i < count; i++)
261 Headers.WriteHeader (i, writer);
262 writer.WriteEndElement ();
265 WriteBody (writer);
266 if (Version.Envelope != EnvelopeVersion.None)
267 writer.WriteEndElement ();
270 protected virtual void OnWriteStartBody (
271 XmlDictionaryWriter writer)
273 var dic = Constants.SoapDictionary;
274 writer.WriteStartElement ("s", dic.Add ("Body"), dic.Add (Version.Envelope.Namespace));
275 if (BodyId != null)
276 writer.WriteAttributeString ("u", dic.Add ("Id"), dic.Add (Constants.WsuNamespace), BodyId);
279 protected virtual void OnWriteStartEnvelope (
280 XmlDictionaryWriter writer)
282 var dic = Constants.SoapDictionary;
283 writer.WriteStartElement ("s", dic.Add ("Envelope"), dic.Add (Version.Envelope.Namespace));
284 if (Headers.Action != null && Version.Addressing.Namespace != MessageVersion.None.Addressing.Namespace)
285 writer.WriteXmlnsAttribute ("a", dic.Add (Version.Addressing.Namespace));
286 foreach (MessageHeaderInfo h in Headers)
287 if (h.Id != null) {
288 writer.WriteXmlnsAttribute ("u", dic.Add (Constants.WsuNamespace));
289 break;
293 protected virtual void OnWriteStartHeaders (
294 XmlDictionaryWriter writer)
296 var dic = Constants.SoapDictionary;
297 writer.WriteStartElement ("s", dic.Add ("Header"), dic.Add (Version.Envelope.Namespace));
300 #region factory methods
302 // 1) version, code, reason, action -> 3
303 // 2) version, code, reason, detail, action -> 3
304 // 3) version, fault, action -> SimpleMessage
305 // 4) version, action, body -> 10 or 5
306 // 5) version, action, body, formatter -> 10 or 9
307 // 6) version, action, xmlReader -> 7
308 // 7) version, action, reader -> 9
309 // 8) xmlReader, maxSizeOfHeaders, version -> 11
310 // 9) version, action, body -> SimpleMessage
311 // 10) version, action -> EmptyMessage
312 // 11) reader, maxSizeOfHeaders, version -> XmlReaderMessage
314 // 1)
315 public static Message CreateMessage (MessageVersion version,
316 FaultCode code, string reason, string action)
318 MessageFault fault = MessageFault.CreateFault (code, reason);
319 return CreateMessage (version, fault, action);
322 // 2)
323 public static Message CreateMessage (MessageVersion version,
324 FaultCode code, string reason, object detail,
325 string action)
327 MessageFault fault = MessageFault.CreateFault (
328 code, new FaultReason (reason), detail);
329 return CreateMessage (version, fault, action);
332 // 3)
333 public static Message CreateMessage (MessageVersion version,
334 MessageFault fault, string action)
336 return new SimpleMessage (version, action,
337 new MessageFaultBodyWriter (fault, version), true);
340 // 4)
341 public static Message CreateMessage (MessageVersion version,
342 string action, object body)
344 return body == null ?
345 CreateMessage (version, action) :
346 CreateMessage (version, action, body, new DataContractSerializer (body.GetType ()));
349 // 5)
350 public static Message CreateMessage (MessageVersion version,
351 string action, object body, XmlObjectSerializer xmlFormatter)
353 return body == null ?
354 CreateMessage (version, action) :
355 CreateMessage (
356 version, action,
357 new XmlObjectSerializerBodyWriter (body, xmlFormatter));
360 // 6)
361 public static Message CreateMessage (MessageVersion version,
362 string action, XmlReader body)
364 return CreateMessage (version, action,
365 XmlDictionaryReader.CreateDictionaryReader (body));
368 // 7)
369 public static Message CreateMessage (MessageVersion version,
370 string action, XmlDictionaryReader body)
372 return CreateMessage (version, action,
373 new XmlReaderBodyWriter (body));
376 // 8)
377 public static Message CreateMessage (XmlReader envelopeReader,
378 int maxSizeOfHeaders, MessageVersion version)
380 return CreateMessage (
381 XmlDictionaryReader.CreateDictionaryReader (envelopeReader),
382 maxSizeOfHeaders,
383 version);
386 // Core implementations of CreateMessage.
388 // 9)
389 public static Message CreateMessage (MessageVersion version,
390 string action, BodyWriter body)
392 if (version == null)
393 throw new ArgumentNullException ("version");
394 if (body == null)
395 throw new ArgumentNullException ("body");
396 return new SimpleMessage (version, action, body, false);
399 // 10)
400 public static Message CreateMessage (MessageVersion version,
401 string action)
403 if (version == null)
404 throw new ArgumentNullException ("version");
405 return new EmptyMessage (version, action);
408 // 11)
409 public static Message CreateMessage (
410 XmlDictionaryReader envelopeReader,
411 int maxSizeOfHeaders,
412 MessageVersion version)
414 if (envelopeReader == null)
415 throw new ArgumentNullException ("envelopeReader");
416 if (version == null)
417 throw new ArgumentNullException ("version");
418 return new XmlReaderMessage (version,
419 envelopeReader, maxSizeOfHeaders);
422 #endregion