5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005-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.
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 writer
.WriteStartElement ("z", "anyType", Constants
.MSSerialization
);
141 writer
.WriteAttributeString ("i", "nil", "http://www.w3.org/2001/XMLSchema-instance", "true");
142 writer
.WriteEndElement ();
145 public void WriteBody (XmlDictionaryWriter writer
)
147 if (Version
.Envelope
!= EnvelopeVersion
.None
)
148 WriteStartBody (writer
);
149 WriteBodyContents (writer
);
150 if (Version
.Envelope
!= EnvelopeVersion
.None
)
151 writer
.WriteEndElement ();
154 public void WriteBody (XmlWriter writer
)
156 WriteBody (XmlDictionaryWriter
.CreateDictionaryWriter (writer
));
159 public void WriteBodyContents (XmlDictionaryWriter writer
)
162 OnWriteBodyContents (writer
);
163 else if (Version
.Envelope
== EnvelopeVersion
.None
)
164 WriteXsiNil (writer
);
165 State
= MessageState
.Written
;
168 public void WriteMessage (XmlDictionaryWriter writer
)
170 if (State
!= MessageState
.Created
)
171 throw new InvalidOperationException (String
.Format ("The message is already at {0} state", State
));
173 OnWriteMessage (writer
);
176 public void WriteMessage (XmlWriter writer
)
178 WriteMessage (XmlDictionaryWriter
.CreateDictionaryWriter (writer
));
181 public void WriteStartBody (XmlDictionaryWriter writer
)
183 if (State
!= MessageState
.Created
)
184 throw new InvalidOperationException (String
.Format ("The message is already at {0} state", State
));
186 OnWriteStartBody (writer
);
189 public void WriteStartBody (XmlWriter writer
)
192 XmlDictionaryWriter
.CreateDictionaryWriter (writer
));
195 public void WriteStartEnvelope (XmlDictionaryWriter writer
)
197 if (State
!= MessageState
.Created
)
198 throw new InvalidOperationException (String
.Format ("The message is already at {0} state", State
));
200 OnWriteStartEnvelope (writer
);
204 protected virtual void OnBodyToString (
205 XmlDictionaryWriter writer
)
207 throw new NotImplementedException ();
210 protected virtual void OnClose ()
214 protected virtual MessageBuffer
OnCreateBufferedCopy (
217 var s
= new XmlWriterSettings ();
218 s
.OmitXmlDeclaration
= true;
219 s
.ConformanceLevel
= ConformanceLevel
.Auto
;
220 StringWriter sw
= new StringWriter ();
221 using (XmlDictionaryWriter w
= XmlDictionaryWriter
.CreateDictionaryWriter (XmlWriter
.Create (sw
, s
)))
222 WriteBodyContents (w
);
223 var headers
= new MessageHeaders (Headers
);
224 var props
= new MessageProperties (Properties
);
225 return new DefaultMessageBuffer (maxBufferSize
, headers
, props
, new XmlReaderBodyWriter (sw
.ToString ()), false);
228 protected virtual string OnGetBodyAttribute (
229 string localName
, string ns
)
231 // other than XmlReaderMessage it cannot return anything
235 protected virtual XmlDictionaryReader
OnGetReaderAtBodyContents ()
237 var ws
= new XmlWriterSettings ();
238 ws
.ConformanceLevel
= ConformanceLevel
.Auto
;
239 StringWriter sw
= new StringWriter ();
240 using (XmlDictionaryWriter body
= XmlDictionaryWriter
.CreateDictionaryWriter (XmlWriter
.Create (sw
, ws
))) {
241 WriteBodyContents (body
);
244 var rs
= new XmlReaderSettings ();
245 rs
.ConformanceLevel
= ConformanceLevel
.Auto
;
246 return XmlDictionaryReader
.CreateDictionaryReader (XmlReader
.Create (new StringReader (sw
.ToString ()), rs
));
249 protected abstract void OnWriteBodyContents (
250 XmlDictionaryWriter writer
);
252 protected virtual void OnWriteMessage (
253 XmlDictionaryWriter writer
)
255 if (Version
.Envelope
!= EnvelopeVersion
.None
) {
256 WriteStartEnvelope (writer
);
257 if (Headers
.Count
> 0) {
258 OnWriteStartHeaders (writer
);
259 for (int i
= 0, count
= Headers
.Count
; i
< count
; i
++)
260 Headers
.WriteHeader (i
, writer
);
261 writer
.WriteEndElement ();
265 if (Version
.Envelope
!= EnvelopeVersion
.None
)
266 writer
.WriteEndElement ();
269 protected virtual void OnWriteStartBody (
270 XmlDictionaryWriter writer
)
272 writer
.WriteStartElement ("s", "Body", Version
.Envelope
.Namespace
);
274 writer
.WriteAttributeString ("u", "Id", Constants
.WsuNamespace
, BodyId
);
277 protected virtual void OnWriteStartEnvelope (
278 XmlDictionaryWriter writer
)
280 writer
.WriteStartElement ("s", "Envelope", Version
.Envelope
.Namespace
);
281 if (Headers
.Action
!= null && Version
.Addressing
.Namespace
!= MessageVersion
.None
.Addressing
.Namespace
)
282 writer
.WriteXmlnsAttribute ("a", Version
.Addressing
.Namespace
);
283 foreach (MessageHeaderInfo h
in Headers
)
285 writer
.WriteXmlnsAttribute ("u", Constants
.WsuNamespace
);
290 protected virtual void OnWriteStartHeaders (
291 XmlDictionaryWriter writer
)
293 writer
.WriteStartElement ("s", "Header", Version
.Envelope
.Namespace
);
296 #region factory methods
300 // 3) fault, action -> 10
301 // 4) version, fault -> 10
302 // 5) version, action -> EmptyMessage
303 // 6) action, body -> 12
304 // 7) action, xmlReader -> 8
305 // 8) action, reader -> 16
306 // 10) version, fault, action -> 20
307 // 11) version, action, body -> 14
308 // 12) action, body, formatter -> 14
309 // 13) version, action, body -> 14
310 // 14) version, action, body, formatter -> 20
311 // 15) version, action, xmlReader -> 16
312 // 16) version, action, reader -> 20
313 // 17) xmlReader, maxSizeOfHeaders, version -> 18
314 // 18) reader, maxSizeOfHeaders, version -> ForwardingMessage
315 // 19) action, bodyWriter -> 20
316 // 20) version, action, bodyWriter -> SimpleMessage
318 public static Message
CreateMessage (MessageVersion version
,
319 FaultCode code
, string reason
, string action
)
321 MessageFault fault
= MessageFault
.CreateFault (code
, reason
);
322 return CreateMessage (version
, fault
, action
);
325 public static Message
CreateMessage (MessageVersion version
,
326 FaultCode code
, string reason
, object detail
,
329 MessageFault fault
= MessageFault
.CreateFault (
330 code
, new FaultReason (reason
), detail
);
331 return CreateMessage (version
, fault
, action
);
334 public static Message
CreateMessage (MessageVersion version
,
335 MessageFault fault
, string action
)
337 return new SimpleMessage (version
, action
,
338 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 ()));
349 public static Message
CreateMessage (MessageVersion version
,
350 string action
, object body
, XmlObjectSerializer xmlFormatter
)
352 return body
== null ?
353 CreateMessage (version
, action
) :
356 new XmlObjectSerializerBodyWriter (body
, xmlFormatter
));
359 public static Message
CreateMessage (MessageVersion version
,
360 string action
, XmlReader body
)
362 return CreateMessage (version
, action
,
363 XmlDictionaryReader
.CreateDictionaryReader (body
));
366 public static Message
CreateMessage (MessageVersion version
,
367 string action
, XmlDictionaryReader body
)
369 return CreateMessage (version
, action
,
370 new XmlReaderBodyWriter (body
));
373 public static Message
CreateMessage (XmlReader envelopeReader
,
374 int maxSizeOfHeaders
, MessageVersion version
)
376 return CreateMessage (
377 XmlDictionaryReader
.CreateDictionaryReader (envelopeReader
),
382 // Core implementations of CreateMessage.
384 public static Message
CreateMessage (MessageVersion version
,
385 string action
, BodyWriter body
)
388 throw new ArgumentNullException ("version");
390 throw new ArgumentNullException ("body");
391 return new SimpleMessage (version
, action
, body
, false);
394 public static Message
CreateMessage (MessageVersion version
,
398 throw new ArgumentNullException ("version");
399 return new EmptyMessage (version
, action
);
402 public static Message
CreateMessage (
403 XmlDictionaryReader envelopeReader
,
404 int maxSizeOfHeaders
,
405 MessageVersion version
)
407 if (envelopeReader
== null)
408 throw new ArgumentNullException ("envelopeReader");
410 throw new ArgumentNullException ("version");
411 return new XmlReaderMessage (version
,
412 envelopeReader
, maxSizeOfHeaders
);