File: MessageHeader.cs

package info (click to toggle)
mono 4.6.2.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 778,148 kB
  • ctags: 914,052
  • sloc: cs: 5,779,509; xml: 2,773,713; ansic: 432,645; sh: 14,749; makefile: 12,361; perl: 2,488; python: 1,434; cpp: 849; asm: 531; sql: 95; sed: 16; php: 1
file content (332 lines) | stat: -rw-r--r-- 11,306 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
//
// System.ServiceModel.MessageHeader.cs
//
// Author: Duncan Mak (duncan@novell.com)
//	   Atsushi Enomoto (atsushi@ximian.com)
//
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.IO;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Xml;

namespace System.ServiceModel.Channels
{
	public abstract class MessageHeader : MessageHeaderInfo
	{
		static readonly XmlWriterSettings writer_settings;

		static MessageHeader ()
		{
			writer_settings = new XmlWriterSettings ();
			writer_settings.OmitXmlDeclaration = true;
			writer_settings.Indent = true;
		}

		protected MessageHeader () {}

		static string default_actor = String.Empty;
		static bool default_is_ref = false;
		static bool default_must_understand = false;
		static bool default_relay = false;

		public static MessageHeader CreateHeader (string name, string ns, object value)
		{
			return CreateHeader (name, ns, value, default_must_understand);
		}

		public static MessageHeader CreateHeader (string name, string ns, object value, bool mustUnderstand)
		{
			return CreateHeader (name, ns, value, mustUnderstand, default_actor);
		}

		public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer)
		{
			return CreateHeader (name, ns, value, serializer, default_must_understand, 
					     default_actor, default_relay);
		}

		public static MessageHeader CreateHeader (string name, string ns, object value, 
						   bool mustUnderstand, string actor)
		{
			return CreateHeader (name, ns, value, mustUnderstand, actor, default_relay);
		}

		public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer, 
						   bool mustUnderstand)
		{
			return CreateHeader (name, ns, value, serializer, mustUnderstand, default_actor, default_relay);
		}
		
		public static MessageHeader CreateHeader (string name, string ns, object value, 
						   bool mustUnderstand, string actor, bool relay)
		{
			return CreateHeader (name, ns, value, new DataContractSerializer (value.GetType ()),
					mustUnderstand, actor, relay);
		}

		public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer,
						   bool mustUnderstand, string actor)
		{
			return CreateHeader (name, ns, value, serializer, mustUnderstand, actor, default_relay);
		}
		
		public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer serializer,
						   bool mustUnderstand, string actor, bool relay)
		{
			// FIXME: how to get IsReferenceParameter ?
			return new DefaultMessageHeader (name, ns, value, serializer, default_is_ref, mustUnderstand, actor, relay);
		}

		public virtual bool IsMessageVersionSupported (MessageVersion messageVersion)
		{
			if (messageVersion.Envelope == EnvelopeVersion.Soap12)
				if (Actor == EnvelopeVersion.Soap11.NextDestinationActorValue)
					return false;

			if (messageVersion.Envelope == EnvelopeVersion.Soap11)
				if (Actor == EnvelopeVersion.Soap12.NextDestinationActorValue ||
				    Actor == EnvelopeVersion.Soap12UltimateReceiver)
					return false;

			// by default, it's always supported
			return true;
		}

		protected abstract void OnWriteHeaderContents (XmlDictionaryWriter writer, MessageVersion messageVersion);

		protected virtual void OnWriteStartHeader (XmlDictionaryWriter writer, MessageVersion messageVersion)
		{
			var dic = Constants.SoapDictionary;
			XmlDictionaryString name, ns;
			var prefix = Prefix ?? (Namespace.Length > 0 ? writer.LookupPrefix (Namespace) : String.Empty);
			if (dic.TryLookup (Name, out name) && dic.TryLookup (Namespace, out ns))
				writer.WriteStartElement (prefix, name, ns);
			else
				writer.WriteStartElement (prefix, this.Name, this.Namespace);
			WriteHeaderAttributes (writer, messageVersion);
		}

		public override string ToString ()
		{
			StringBuilder sb = new StringBuilder ();

			XmlWriter w = XmlWriter.Create (sb, writer_settings);

			WriteHeader (w, MessageVersion.Default);
			w.Close ();

			return sb.ToString ();
		}

		public void WriteHeader (XmlDictionaryWriter writer, MessageVersion messageVersion)
		{
			if (writer == null)
				throw new ArgumentNullException ("writer is null.");

			if (messageVersion == null)
				throw new ArgumentNullException ("messageVersion is null.");

			if (messageVersion.Envelope == EnvelopeVersion.None)
				return;

			WriteStartHeader (writer, messageVersion);
			WriteHeaderContents (writer, messageVersion);

			writer.WriteEndElement ();
		}

		public void WriteHeader (XmlWriter writer, MessageVersion messageVersion)
		{
			WriteHeader (XmlDictionaryWriter.CreateDictionaryWriter (writer), messageVersion);
		}

		protected void WriteHeaderAttributes (XmlDictionaryWriter writer, MessageVersion messageVersion)
		{
			var dic = Constants.SoapDictionary;
			if (Id != null)
				writer.WriteAttributeString ("u", dic.Add ("Id"), dic.Add (Constants.WsuNamespace), Id);
			if (!String.IsNullOrEmpty (Actor)) {
				if (messageVersion.Envelope == EnvelopeVersion.Soap11) 
					writer.WriteAttributeString ("s", dic.Add ("actor"), dic.Add (messageVersion.Envelope.Namespace), Actor);

				if (messageVersion.Envelope == EnvelopeVersion.Soap12) 
					writer.WriteAttributeString ("s", dic.Add ("role"), dic.Add (messageVersion.Envelope.Namespace), Actor);
			}

			// mustUnderstand is the same across SOAP 1.1 and 1.2
			if (MustUnderstand == true)
				writer.WriteAttributeString ("s", dic.Add ("mustUnderstand"), dic.Add (messageVersion.Envelope.Namespace), "1");

			// relay is only available on SOAP 1.2
			if (Relay == true && messageVersion.Envelope == EnvelopeVersion.Soap12)
				writer.WriteAttributeString ("s", dic.Add ("relay"), dic.Add (messageVersion.Envelope.Namespace), "true");
		}

		public void WriteHeaderContents (XmlDictionaryWriter writer, MessageVersion messageVersion)
		{
			this.OnWriteHeaderContents (writer, messageVersion);
		}

		public void WriteStartHeader (XmlDictionaryWriter writer, MessageVersion messageVersion)
		{
			this.OnWriteStartHeader (writer, messageVersion);
		}

		public override string Actor { get { return default_actor; }}

		public override bool IsReferenceParameter { get { return default_is_ref; }}

		public override bool MustUnderstand { get { return default_must_understand; }}

		public override bool Relay { get { return default_relay; }}

		internal class XmlMessageHeader : MessageHeader
		{
			bool is_ref, must_understand, relay;
			string actor;
#if NET_2_1
			string body;
#else
			// This is required to completely clone body xml that 
			// does not introduce additional xmlns declarations that
			// blocks canonicalized copy of the input XML.
			XmlDocument body;
#endif
			string local_name;
			string namespace_uri;

			public XmlMessageHeader (XmlReader reader, MessageVersion version)
			{
				var soapNS = version.Envelope.Namespace;
				var addrNS = version.Addressing.Namespace;
				Prefix = reader.Prefix;
				Id = reader.GetAttribute ("Id", Constants.WsuNamespace);

				string s = reader.GetAttribute ("relay", soapNS);
				relay = s != null ? XmlConvert.ToBoolean (s) : false;
				s = reader.GetAttribute ("mustUnderstand", soapNS);
				must_understand = s != null ? XmlConvert.ToBoolean (s) : false;
				actor = reader.GetAttribute ("actor", soapNS) ?? String.Empty;

				s = reader.GetAttribute ("IsReferenceParameter", addrNS);
				is_ref = s != null ? XmlConvert.ToBoolean (s) : false;

				local_name = reader.LocalName;
				namespace_uri = reader.NamespaceURI;
#if NET_2_1
				body = reader.ReadOuterXml ();
#else
				body = new XmlDocument ();
				var w = body.CreateNavigator ().AppendChild ();
				w.WriteNode (reader, false);
				w.Close ();
#endif
			}

			public XmlReader CreateReader ()
			{
#if NET_2_1
				var reader = XmlReader.Create (new StringReader (body));
#else
				var reader = new XmlNodeReader (body);
#endif
				reader.MoveToContent ();
				return reader;
			}

			protected override void OnWriteHeaderContents (
				XmlDictionaryWriter writer, MessageVersion version)
			{
				var r = CreateReader ();
				r.MoveToContent ();
				if (r.IsEmptyElement)
					return; // write nothing
				for (r.Read (); r.NodeType != XmlNodeType.EndElement;)
					writer.WriteNode (r, false);
			}

			public override string Actor { get { return actor; }}

			public override bool IsReferenceParameter { get { return is_ref; }}

			public override bool MustUnderstand { get { return must_understand; }}

			public override string Name { get { return local_name; }}

			public override string Namespace { get { return namespace_uri; }}

			public override bool Relay { get { return relay; }}
		}

		internal class DefaultMessageHeader : MessageHeader
		{
			string actor, name, ns;
			object value;
			XmlObjectSerializer formatter;
			bool is_ref, must_understand, relay;
			
			internal DefaultMessageHeader (string name, string ns, object value, XmlObjectSerializer formatter, 
						       bool isReferenceParameter,
						       bool mustUnderstand, string actor, bool relay)
			{
				this.name = name;
				this.ns = ns;
				this.value = value;
				this.formatter = formatter;
				this.is_ref = isReferenceParameter;
				this.must_understand = mustUnderstand;
				this.actor = actor ?? String.Empty;
				this.relay = relay;
			}

			protected override void OnWriteHeaderContents (XmlDictionaryWriter writer,
								       MessageVersion version)
			{
				// FIXME: it's a nasty workaround just to avoid UniqueId output as a string, for bug #577139.
				if (Value is UniqueId)
					writer.WriteValue ((UniqueId) Value);
				else
					this.formatter.WriteObjectContent (writer, value);
			}

			public object Value { get { return value; } }

			public override string Actor { get { return actor; }}

			public override bool IsReferenceParameter { get { return is_ref; }}

			public override bool MustUnderstand { get { return must_understand; }}

			public override string Name { get { return name; }}

			public override string Namespace { get { return ns; }}

			public override bool Relay { get { return relay; }}
		}
	}
}