5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005-2006,2010 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.
30 using System
.Runtime
.Serialization
;
32 using System
.Xml
.Schema
;
35 namespace System
.ServiceModel
.Channels
37 public abstract class Message
: IDisposable
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
{
57 public virtual bool IsFault
{
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; }
79 State
= MessageState
.Closed
;
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
));
88 return OnCreateBufferedCopy (maxBufferSize
);
90 State
= MessageState
.Copied
;
94 void IDisposable
.Dispose ()
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
;
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
)) {
131 return sw
.ToString ();
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
)
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
)
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
);
205 protected virtual void OnBodyToString (
206 XmlDictionaryWriter writer
)
208 throw new NotImplementedException ();
211 protected virtual void OnClose ()
215 protected virtual MessageBuffer
OnCreateBufferedCopy (
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
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 ();
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
));
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
)
288 writer
.WriteXmlnsAttribute ("u", dic
.Add (Constants
.WsuNamespace
));
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
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
);
323 public static Message
CreateMessage (MessageVersion version
,
324 FaultCode code
, string reason
, object detail
,
327 MessageFault fault
= MessageFault
.CreateFault (
328 code
, new FaultReason (reason
), detail
);
329 return CreateMessage (version
, fault
, action
);
333 public static Message
CreateMessage (MessageVersion version
,
334 MessageFault fault
, string action
)
336 return new SimpleMessage (version
, action
,
337 new MessageFaultBodyWriter (fault
, version
), true);
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 ()));
350 public static Message
CreateMessage (MessageVersion version
,
351 string action
, object body
, XmlObjectSerializer xmlFormatter
)
353 return body
== null ?
354 CreateMessage (version
, action
) :
357 new XmlObjectSerializerBodyWriter (body
, xmlFormatter
));
361 public static Message
CreateMessage (MessageVersion version
,
362 string action
, XmlReader body
)
364 return CreateMessage (version
, action
,
365 XmlDictionaryReader
.CreateDictionaryReader (body
));
369 public static Message
CreateMessage (MessageVersion version
,
370 string action
, XmlDictionaryReader body
)
372 return CreateMessage (version
, action
,
373 new XmlReaderBodyWriter (body
));
377 public static Message
CreateMessage (XmlReader envelopeReader
,
378 int maxSizeOfHeaders
, MessageVersion version
)
380 return CreateMessage (
381 XmlDictionaryReader
.CreateDictionaryReader (envelopeReader
),
386 // Core implementations of CreateMessage.
389 public static Message
CreateMessage (MessageVersion version
,
390 string action
, BodyWriter body
)
393 throw new ArgumentNullException ("version");
395 throw new ArgumentNullException ("body");
396 return new SimpleMessage (version
, action
, body
, false);
400 public static Message
CreateMessage (MessageVersion version
,
404 throw new ArgumentNullException ("version");
405 return new EmptyMessage (version
, action
);
409 public static Message
CreateMessage (
410 XmlDictionaryReader envelopeReader
,
411 int maxSizeOfHeaders
,
412 MessageVersion version
)
414 if (envelopeReader
== null)
415 throw new ArgumentNullException ("envelopeReader");
417 throw new ArgumentNullException ("version");
418 return new XmlReaderMessage (version
,
419 envelopeReader
, maxSizeOfHeaders
);