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);
167 public void WriteMessage (XmlDictionaryWriter writer)
169 if (State != MessageState.Created)
170 throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
171 State = MessageState.Written;
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 && State != MessageState.Written)
184 throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
185 State = MessageState.Written;
187 OnWriteStartBody (writer);
190 public void WriteStartBody (XmlWriter writer)
193 XmlDictionaryWriter.CreateDictionaryWriter (writer));
196 public void WriteStartEnvelope (XmlDictionaryWriter writer)
198 if (State != MessageState.Created && State != MessageState.Written)
199 throw new InvalidOperationException (String.Format ("The message is already at {0} state", State));
200 State = MessageState.Written;
202 OnWriteStartEnvelope (writer);
206 protected virtual void OnBodyToString (
207 XmlDictionaryWriter writer)
209 throw new NotImplementedException ();
212 protected virtual void OnClose ()
216 protected virtual MessageBuffer OnCreateBufferedCopy (
219 var s = new XmlWriterSettings ();
220 s.OmitXmlDeclaration = true;
221 s.ConformanceLevel = ConformanceLevel.Auto;
222 StringWriter sw = new StringWriter ();
223 using (XmlDictionaryWriter w = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (sw, s)))
224 WriteBodyContents (w);
225 var headers = new MessageHeaders (Headers);
226 var props = new MessageProperties (Properties);
227 return new DefaultMessageBuffer (maxBufferSize, headers, props, new XmlReaderBodyWriter (sw.ToString ()), false);
230 protected virtual string OnGetBodyAttribute (
231 string localName, string ns)
233 // other than XmlReaderMessage it cannot return anything
237 protected virtual XmlDictionaryReader OnGetReaderAtBodyContents ()
239 var ws = new XmlWriterSettings ();
240 ws.ConformanceLevel = ConformanceLevel.Auto;
241 StringWriter sw = new StringWriter ();
242 using (XmlDictionaryWriter body = XmlDictionaryWriter.CreateDictionaryWriter (XmlWriter.Create (sw, ws))) {
243 WriteBodyContents (body);
246 var rs = new XmlReaderSettings ();
247 rs.ConformanceLevel = ConformanceLevel.Auto;
248 return XmlDictionaryReader.CreateDictionaryReader (XmlReader.Create (new StringReader (sw.ToString ()), rs));
251 protected abstract void OnWriteBodyContents (
252 XmlDictionaryWriter writer);
254 protected virtual void OnWriteMessage (
255 XmlDictionaryWriter writer)
257 if (Version.Envelope != EnvelopeVersion.None) {
258 WriteStartEnvelope (writer);
259 if (Headers.Count > 0) {
260 OnWriteStartHeaders (writer);
261 for (int i = 0, count = Headers.Count; i < count; i++)
262 Headers.WriteHeader (i, writer);
263 writer.WriteEndElement ();
267 if (Version.Envelope != EnvelopeVersion.None)
268 writer.WriteEndElement ();
271 protected virtual void OnWriteStartBody (
272 XmlDictionaryWriter writer)
274 writer.WriteStartElement ("s", "Body", Version.Envelope.Namespace);
276 writer.WriteAttributeString ("u", "Id", Constants.WsuNamespace, BodyId);
279 protected virtual void OnWriteStartEnvelope (
280 XmlDictionaryWriter writer)
282 writer.WriteStartElement ("s", "Envelope", Version.Envelope.Namespace);
283 if (Headers.Action != null && Version.Addressing.Namespace != MessageVersion.None.Addressing.Namespace)
284 writer.WriteXmlnsAttribute ("a", Version.Addressing.Namespace);
285 foreach (MessageHeaderInfo h in Headers)
287 writer.WriteXmlnsAttribute ("u", Constants.WsuNamespace);
292 protected virtual void OnWriteStartHeaders (
293 XmlDictionaryWriter writer)
295 writer.WriteStartElement ("s", "Header", Version.Envelope.Namespace);
298 #region factory methods
302 // 3) fault, action -> 10
303 // 4) version, fault -> 10
304 // 5) version, action -> EmptyMessage
305 // 6) action, body -> 12
306 // 7) action, xmlReader -> 8
307 // 8) action, reader -> 16
308 // 10) version, fault, action -> 20
309 // 11) version, action, body -> 14
310 // 12) action, body, formatter -> 14
311 // 13) version, action, body -> 14
312 // 14) version, action, body, formatter -> 20
313 // 15) version, action, xmlReader -> 16
314 // 16) version, action, reader -> 20
315 // 17) xmlReader, maxSizeOfHeaders, version -> 18
316 // 18) reader, maxSizeOfHeaders, version -> ForwardingMessage
317 // 19) action, bodyWriter -> 20
318 // 20) version, action, bodyWriter -> SimpleMessage
320 public static Message CreateMessage (MessageVersion version,
321 FaultCode code, string reason, string action)
323 MessageFault fault = MessageFault.CreateFault (code, reason);
324 return CreateMessage (version, fault, action);
327 public static Message CreateMessage (MessageVersion version,
328 FaultCode code, string reason, object detail,
331 MessageFault fault = MessageFault.CreateFault (
332 code, new FaultReason (reason), detail);
333 return CreateMessage (version, fault, action);
336 public static Message CreateMessage (MessageVersion version,
337 MessageFault fault, string action)
339 return new SimpleMessage (version, action,
340 new MessageFaultBodyWriter (fault, version), true);
343 public static Message CreateMessage (MessageVersion version,
344 string action, object body)
346 return body == null ?
347 CreateMessage (version, action) :
348 CreateMessage (version, action, body, new DataContractSerializer (body.GetType ()));
351 public static Message CreateMessage (MessageVersion version,
352 string action, object body, XmlObjectSerializer xmlFormatter)
354 return body == null ?
355 CreateMessage (version, action) :
358 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));
368 public static Message CreateMessage (MessageVersion version,
369 string action, XmlDictionaryReader body)
371 return CreateMessage (version, action,
372 new XmlReaderBodyWriter (body));
375 public static Message CreateMessage (XmlReader envelopeReader,
376 int maxSizeOfHeaders, MessageVersion version)
378 return CreateMessage (
379 XmlDictionaryReader.CreateDictionaryReader (envelopeReader),
384 // Core implementations of CreateMessage.
386 public static Message CreateMessage (MessageVersion version,
387 string action, BodyWriter body)
390 throw new ArgumentNullException ("version");
392 throw new ArgumentNullException ("body");
393 return new SimpleMessage (version, action, body, false);
396 public static Message CreateMessage (MessageVersion version,
400 throw new ArgumentNullException ("version");
401 return new EmptyMessage (version, action);
404 public static Message CreateMessage (
405 XmlDictionaryReader envelopeReader,
406 int maxSizeOfHeaders,
407 MessageVersion version)
409 if (envelopeReader == null)
410 throw new ArgumentNullException ("envelopeReader");
412 throw new ArgumentNullException ("version");
413 return new XmlReaderMessage (version,
414 envelopeReader, maxSizeOfHeaders);