move to from olive to mcs
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / MessageHeader.cs
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.
27 //
28
29 using System;
30 using System.Runtime.Serialization;
31 using System.ServiceModel;
32 using System.ServiceModel.Channels;
33 using System.Text;
34 using System.Xml;
35
36 namespace System.ServiceModel.Channels
37 {
38         public abstract class MessageHeader : MessageHeaderInfo
39         {
40                 static readonly XmlWriterSettings writer_settings;
41
42                 static MessageHeader ()
43                 {
44                         writer_settings = new XmlWriterSettings ();
45                         writer_settings.OmitXmlDeclaration = true;
46                         writer_settings.Indent = true;
47                 }
48
49                 protected MessageHeader () {}
50
51                 static string default_actor = String.Empty;
52                 static bool default_is_ref = false;
53                 static bool default_must_understand = false;
54                 static bool default_relay = false;
55                 static Type [] knownTypes = new Type [1] {typeof (EndpointAddress10)};
56
57                 internal static MessageHeader CreateInternalHeader (XmlElement el, string soap_ns)
58                 {
59                         return new RawMessageHeader (el, soap_ns);
60                 }
61
62                 public static MessageHeader CreateHeader (string name, string ns, object value)
63                 {
64                         return CreateHeader (name, ns, value, default_must_understand);
65                 }
66
67                 public static MessageHeader CreateHeader (string name, string ns, object value, bool must_understand)
68                 {
69                         return CreateHeader (name, ns, value, must_understand, default_actor);
70                 }
71
72                 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter)
73                 {
74                         return CreateHeader (name, ns, value, formatter, default_must_understand, 
75                                              default_actor, default_relay);
76                 }
77
78                 public static MessageHeader CreateHeader (string name, string ns, object value, 
79                                                    bool must_understand, string actor)
80                 {
81                         return CreateHeader (name, ns, value, must_understand, actor, default_relay);
82                 }
83
84                 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter, 
85                                                    bool must_understand)
86                 {
87                         return CreateHeader (name, ns, value, formatter, must_understand, default_actor, default_relay);
88                 }
89                 
90                 public static MessageHeader CreateHeader (string name, string ns, object value, 
91                                                    bool must_understand, string actor, bool relay)
92                 {
93                         return CreateHeader (name, ns, value, new DataContractSerializer (value.GetType (), knownTypes),
94                                         must_understand, actor, relay);
95                 }
96
97                 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
98                                                    bool must_understand, string actor)
99                 {
100                         return CreateHeader (name, ns, value, formatter, must_understand, actor, default_relay);
101                 }
102                 
103                 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
104                                                    bool must_understand, string actor, bool relay)
105                 {
106                         // FIXME: how to get IsReferenceParameter ?
107                         return new DefaultMessageHeader (name, ns, value, formatter, default_is_ref, must_understand, actor, relay);
108                 }
109
110                 public virtual bool IsMessageVersionSupported (MessageVersion version)
111                 {
112                         if (version.Envelope == EnvelopeVersion.Soap12)
113                                 if (Actor == EnvelopeVersion.Soap11.NextDestinationActorValue)
114                                         return false;
115
116                         if (version.Envelope == EnvelopeVersion.Soap11)
117                                 if (Actor == EnvelopeVersion.Soap12.NextDestinationActorValue ||
118                                     Actor == EnvelopeVersion.Soap12UltimateReceiver)
119                                         return false;
120
121                         // by default, it's always supported
122                         return true;
123                 }
124
125                 protected abstract void OnWriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version);
126
127                 protected virtual void OnWriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
128                 {
129                         writer.WriteStartElement (this.Name, this.Namespace);
130                         WriteHeaderAttributes (writer, version);
131                 }
132
133                 public override string ToString ()
134                 {
135                         StringBuilder sb = new StringBuilder ();
136
137                         XmlWriter w = XmlWriter.Create (sb, writer_settings);
138
139                         WriteHeader (w, MessageVersion.Default);
140                         w.Close ();
141
142                         return sb.ToString ();
143                 }
144
145                 public void WriteHeader (XmlDictionaryWriter writer, MessageVersion version)
146                 {
147                         if (writer == null)
148                                 throw new ArgumentNullException ("writer is null.");
149
150                         if (version == null)
151                                 throw new ArgumentNullException ("version is null.");
152
153                         if (version.Envelope == EnvelopeVersion.None)
154                                 return;
155
156                         WriteStartHeader (writer, version);
157                         WriteHeaderContents (writer, version);
158
159                         writer.WriteEndElement ();
160                 }
161
162                 public void WriteHeader (XmlWriter writer, MessageVersion version)
163                 {
164                         WriteHeader (XmlDictionaryWriter.CreateDictionaryWriter (writer), version);
165                 }
166
167                 protected void WriteHeaderAttributes (XmlDictionaryWriter writer, MessageVersion version)
168                 {
169                         if (Id != null)
170                                 writer.WriteAttributeString ("u", "Id", Constants.WsuNamespace, Id);
171                         if (Actor != String.Empty) {
172                                 if (version.Envelope == EnvelopeVersion.Soap11) 
173                                         writer.WriteAttributeString ("s", "actor", version.Envelope.Namespace, Actor);
174
175                                 if (version.Envelope == EnvelopeVersion.Soap12) 
176                                         writer.WriteAttributeString ("s", "role", version.Envelope.Namespace, Actor);
177                         }
178
179                         // mustUnderstand is the same across SOAP 1.1 and 1.2
180                         if (MustUnderstand == true)
181                                 writer.WriteAttributeString ("s", "mustUnderstand", version.Envelope.Namespace, "1");
182
183                         // relay is only available on SOAP 1.2
184                         if (Relay == true && version.Envelope == EnvelopeVersion.Soap12)
185                                 writer.WriteAttributeString ("s", "relay", version.Envelope.Namespace, "true");
186                 }
187
188                 public void WriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version)
189                 {
190                         this.OnWriteHeaderContents (writer, version);
191                 }
192
193                 public void WriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
194                 {
195                         this.OnWriteStartHeader (writer, version);
196                 }
197
198                 public override string Actor { get { return default_actor; }}
199
200                 public override bool IsReferenceParameter { get { return default_is_ref; }}
201
202                 public override bool MustUnderstand { get { return default_must_understand; }}
203
204                 public override bool Relay { get { return default_relay; }}
205
206                 internal class RawMessageHeader : MessageHeader
207                 {
208                         XmlElement source;
209                         string soap_ns;
210                         bool is_ref, must_understand, relay;
211                         string actor;
212
213                         public RawMessageHeader (XmlElement source, string soap_ns)
214                         {
215                                 this.source = source;
216
217                                 Id = source.HasAttribute ("Id", Constants.WsuNamespace) ?
218                                         source.GetAttribute ("Id", Constants.WsuNamespace) :
219                                         null;
220
221                                 // FIXME: fill is_ref
222                                 string s = source.GetAttribute ("relay", soap_ns);
223                                 relay = s.Length > 0 ? XmlConvert.ToBoolean (s) : false;
224                                 s = source.GetAttribute ("mustUnderstand", soap_ns);
225                                 must_understand = s.Length > 0 ? XmlConvert.ToBoolean (s) : false;
226                                 actor = source.GetAttribute ("actor", soap_ns);
227                         }
228
229                         public XmlReader CreateReader ()
230                         {
231                                 return new XmlNodeReader (source);
232                         }
233
234                         protected override void OnWriteHeaderContents (
235                                 XmlDictionaryWriter writer, MessageVersion version)
236                         {
237                                 source.WriteContentTo (writer);
238                         }
239
240                         public override string Actor { get { return actor; }}
241
242                         public override bool IsReferenceParameter { get { return is_ref; }}
243
244                         public override bool MustUnderstand { get { return must_understand; }}
245
246                         public override string Name { get { return source.LocalName; }}
247
248                         public override string Namespace { get { return source.NamespaceURI; }}
249
250                         public override bool Relay { get { return relay; }}
251                 }
252
253                 internal class DefaultMessageHeader : MessageHeader
254                 {
255                         string actor, name, ns;
256                         object value;
257                         XmlObjectSerializer formatter;
258                         bool is_ref, must_understand, relay;
259                         
260                         internal DefaultMessageHeader (string name, string ns, object value, XmlObjectSerializer formatter, 
261                                                        bool isReferenceParameter,
262                                                        bool mustUnderstand, string actor, bool relay)
263                         {
264                                 this.name = name;
265                                 this.ns = ns;
266                                 this.value = value;
267                                 this.formatter = formatter;
268                                 this.is_ref = isReferenceParameter;
269                                 this.must_understand = mustUnderstand;
270                                 this.actor = actor;
271                                 this.relay = relay;
272                         }
273
274                         protected override void OnWriteHeaderContents (XmlDictionaryWriter writer,
275                                                                        MessageVersion version)
276                         {
277                                 if (value is EndpointAddress)
278                                         ((EndpointAddress) value).WriteTo (version.Addressing, writer, name, ns);
279                                 else
280                                         this.formatter.WriteObjectContent (writer, value);
281                         }
282
283                         public override string Actor { get { return actor; }}
284
285                         public override bool IsReferenceParameter { get { return is_ref; }}
286
287                         public override bool MustUnderstand { get { return must_understand; }}
288
289                         public override string Name { get { return name; }}
290
291                         public override string Namespace { get { return ns; }}
292
293                         public override bool Relay { get { return relay; }}
294                 }
295         }
296 }