2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Channels / MessageHeader.cs
blobc2abe80e7555a734b4dd60046e20df8635d17425
1 //
2 // System.ServiceModel.MessageHeader.cs
3 //
4 // Author: Duncan Mak (duncan@novell.com)
5 // Atsushi Enomoto (atsushi@ximian.com)
6 //
7 // Copyright (C) 2005 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.
29 using System;
30 using System.IO;
31 using System.Runtime.Serialization;
32 using System.ServiceModel;
33 using System.ServiceModel.Channels;
34 using System.Text;
35 using System.Xml;
37 namespace System.ServiceModel.Channels
39 public abstract class MessageHeader : MessageHeaderInfo
41 static readonly XmlWriterSettings writer_settings;
43 static MessageHeader ()
45 writer_settings = new XmlWriterSettings ();
46 writer_settings.OmitXmlDeclaration = true;
47 writer_settings.Indent = true;
50 protected MessageHeader () {}
52 static string default_actor = String.Empty;
53 static bool default_is_ref = false;
54 static bool default_must_understand = false;
55 static bool default_relay = false;
57 public static MessageHeader CreateHeader (string name, string ns, object value)
59 return CreateHeader (name, ns, value, default_must_understand);
62 public static MessageHeader CreateHeader (string name, string ns, object value, bool must_understand)
64 return CreateHeader (name, ns, value, must_understand, default_actor);
67 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter)
69 return CreateHeader (name, ns, value, formatter, default_must_understand,
70 default_actor, default_relay);
73 public static MessageHeader CreateHeader (string name, string ns, object value,
74 bool must_understand, string actor)
76 return CreateHeader (name, ns, value, must_understand, actor, default_relay);
79 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
80 bool must_understand)
82 return CreateHeader (name, ns, value, formatter, must_understand, default_actor, default_relay);
85 public static MessageHeader CreateHeader (string name, string ns, object value,
86 bool must_understand, string actor, bool relay)
88 return CreateHeader (name, ns, value, new DataContractSerializer (value.GetType ()),
89 must_understand, actor, relay);
92 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
93 bool must_understand, string actor)
95 return CreateHeader (name, ns, value, formatter, must_understand, actor, default_relay);
98 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
99 bool must_understand, string actor, bool relay)
101 // FIXME: how to get IsReferenceParameter ?
102 return new DefaultMessageHeader (name, ns, value, formatter, default_is_ref, must_understand, actor, relay);
105 public virtual bool IsMessageVersionSupported (MessageVersion version)
107 if (version.Envelope == EnvelopeVersion.Soap12)
108 if (Actor == EnvelopeVersion.Soap11.NextDestinationActorValue)
109 return false;
111 if (version.Envelope == EnvelopeVersion.Soap11)
112 if (Actor == EnvelopeVersion.Soap12.NextDestinationActorValue ||
113 Actor == EnvelopeVersion.Soap12UltimateReceiver)
114 return false;
116 // by default, it's always supported
117 return true;
120 protected abstract void OnWriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version);
122 protected virtual void OnWriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
124 var dic = Constants.SoapDictionary;
125 XmlDictionaryString name, ns;
126 var prefix = Namespace.Length > 0 ? writer.LookupPrefix (Namespace) : String.Empty;
127 if (dic.TryLookup (Name, out name) && dic.TryLookup (Namespace, out ns))
128 writer.WriteStartElement (prefix, name, ns);
129 else
130 writer.WriteStartElement (prefix, this.Name, this.Namespace);
131 WriteHeaderAttributes (writer, version);
134 public override string ToString ()
136 StringBuilder sb = new StringBuilder ();
138 XmlWriter w = XmlWriter.Create (sb, writer_settings);
140 WriteHeader (w, MessageVersion.Default);
141 w.Close ();
143 return sb.ToString ();
146 public void WriteHeader (XmlDictionaryWriter writer, MessageVersion version)
148 if (writer == null)
149 throw new ArgumentNullException ("writer is null.");
151 if (version == null)
152 throw new ArgumentNullException ("version is null.");
154 if (version.Envelope == EnvelopeVersion.None)
155 return;
157 WriteStartHeader (writer, version);
158 WriteHeaderContents (writer, version);
160 writer.WriteEndElement ();
163 public void WriteHeader (XmlWriter writer, MessageVersion version)
165 WriteHeader (XmlDictionaryWriter.CreateDictionaryWriter (writer), version);
168 protected void WriteHeaderAttributes (XmlDictionaryWriter writer, MessageVersion version)
170 var dic = Constants.SoapDictionary;
171 if (Id != null)
172 writer.WriteAttributeString ("u", dic.Add ("Id"), dic.Add (Constants.WsuNamespace), Id);
173 if (Actor != String.Empty) {
174 if (version.Envelope == EnvelopeVersion.Soap11)
175 writer.WriteAttributeString ("s", dic.Add ("actor"), dic.Add (version.Envelope.Namespace), Actor);
177 if (version.Envelope == EnvelopeVersion.Soap12)
178 writer.WriteAttributeString ("s", dic.Add ("role"), dic.Add (version.Envelope.Namespace), Actor);
181 // mustUnderstand is the same across SOAP 1.1 and 1.2
182 if (MustUnderstand == true)
183 writer.WriteAttributeString ("s", dic.Add ("mustUnderstand"), dic.Add (version.Envelope.Namespace), "1");
185 // relay is only available on SOAP 1.2
186 if (Relay == true && version.Envelope == EnvelopeVersion.Soap12)
187 writer.WriteAttributeString ("s", dic.Add ("relay"), dic.Add (version.Envelope.Namespace), "true");
190 public void WriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version)
192 this.OnWriteHeaderContents (writer, version);
195 public void WriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
197 this.OnWriteStartHeader (writer, version);
200 public override string Actor { get { return default_actor; }}
202 public override bool IsReferenceParameter { get { return default_is_ref; }}
204 public override bool MustUnderstand { get { return default_must_understand; }}
206 public override bool Relay { get { return default_relay; }}
208 internal class RawMessageHeader : MessageHeader
210 string soap_ns;
211 bool is_ref, must_understand, relay;
212 string actor;
213 string body;
214 string local_name;
215 string namespace_uri;
217 public RawMessageHeader (XmlReader reader, string soap_ns)
219 Id = reader.GetAttribute ("Id", Constants.WsuNamespace);
221 string s = reader.GetAttribute ("relay", soap_ns);
222 relay = s != null ? XmlConvert.ToBoolean (s) : false;
223 s = reader.GetAttribute ("mustUnderstand", soap_ns);
224 must_understand = s != null ? XmlConvert.ToBoolean (s) : false;
225 actor = reader.GetAttribute ("actor", soap_ns) ?? String.Empty;
227 s = reader.GetAttribute ("IsReferenceParameter", Constants.WsaNamespace);
228 is_ref = s != null ? XmlConvert.ToBoolean (s) : false;
230 local_name = reader.LocalName;
231 namespace_uri = reader.NamespaceURI;
232 body = reader.ReadOuterXml ();
235 public XmlReader CreateReader ()
237 var reader = XmlReader.Create (new StringReader (body));
238 reader.MoveToContent ();
239 return reader;
242 protected override void OnWriteHeaderContents (
243 XmlDictionaryWriter writer, MessageVersion version)
245 var r = CreateReader ();
246 r.MoveToContent ();
247 if (r.IsEmptyElement)
248 return; // write nothing
249 for (r.Read (); r.NodeType != XmlNodeType.EndElement;)
250 writer.WriteNode (r, false);
253 public override string Actor { get { return actor; }}
255 public override bool IsReferenceParameter { get { return is_ref; }}
257 public override bool MustUnderstand { get { return must_understand; }}
259 public override string Name { get { return local_name; }}
261 public override string Namespace { get { return namespace_uri; }}
263 public override bool Relay { get { return relay; }}
266 internal class DefaultMessageHeader : MessageHeader
268 string actor, name, ns;
269 object value;
270 XmlObjectSerializer formatter;
271 bool is_ref, must_understand, relay;
273 internal DefaultMessageHeader (string name, string ns, object value, XmlObjectSerializer formatter,
274 bool isReferenceParameter,
275 bool mustUnderstand, string actor, bool relay)
277 this.name = name;
278 this.ns = ns;
279 this.value = value;
280 this.formatter = formatter;
281 this.is_ref = isReferenceParameter;
282 this.must_understand = mustUnderstand;
283 this.actor = actor;
284 this.relay = relay;
287 protected override void OnWriteHeaderContents (XmlDictionaryWriter writer,
288 MessageVersion version)
290 // FIXME: it's a nasty workaround just to avoid UniqueId output as a string, for bug #577139.
291 if (Value is UniqueId)
292 writer.WriteValue ((UniqueId) Value);
293 else
294 this.formatter.WriteObjectContent (writer, value);
297 public object Value { get { return value; } }
299 public override string Actor { get { return actor; }}
301 public override bool IsReferenceParameter { get { return is_ref; }}
303 public override bool MustUnderstand { get { return must_understand; }}
305 public override string Name { get { return name; }}
307 public override string Namespace { get { return ns; }}
309 public override bool Relay { get { return relay; }}