2
0

AddressHeader.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System.Runtime;
  7. using System.Runtime.Serialization;
  8. using System.ServiceModel;
  9. using System.ServiceModel.Dispatcher;
  10. using System.Text;
  11. using System.Xml;
  12. public abstract class AddressHeader
  13. {
  14. ParameterHeader header;
  15. protected AddressHeader()
  16. {
  17. }
  18. internal bool IsReferenceProperty
  19. {
  20. get
  21. {
  22. BufferedAddressHeader bah = this as BufferedAddressHeader;
  23. return bah != null && bah.IsReferencePropertyHeader;
  24. }
  25. }
  26. public abstract string Name { get; }
  27. public abstract string Namespace { get; }
  28. public static AddressHeader CreateAddressHeader(object value)
  29. {
  30. Type type = GetObjectType(value);
  31. return CreateAddressHeader(value, DataContractSerializerDefaults.CreateSerializer(type, int.MaxValue/*maxItems*/));
  32. }
  33. public static AddressHeader CreateAddressHeader(object value, XmlObjectSerializer serializer)
  34. {
  35. if (serializer == null)
  36. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
  37. return new XmlObjectSerializerAddressHeader(value, serializer);
  38. }
  39. public static AddressHeader CreateAddressHeader(string name, string ns, object value)
  40. {
  41. return CreateAddressHeader(name, ns, value, DataContractSerializerDefaults.CreateSerializer(GetObjectType(value), name, ns, int.MaxValue/*maxItems*/));
  42. }
  43. internal static AddressHeader CreateAddressHeader(XmlDictionaryString name, XmlDictionaryString ns, object value)
  44. {
  45. return new DictionaryAddressHeader(name, ns, value);
  46. }
  47. public static AddressHeader CreateAddressHeader(string name, string ns, object value, XmlObjectSerializer serializer)
  48. {
  49. if (serializer == null)
  50. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
  51. return new XmlObjectSerializerAddressHeader(name, ns, value, serializer);
  52. }
  53. static Type GetObjectType(object value)
  54. {
  55. return (value == null) ? typeof(object) : value.GetType();
  56. }
  57. public override bool Equals(object obj)
  58. {
  59. AddressHeader hdr = obj as AddressHeader;
  60. if (hdr == null)
  61. return false;
  62. StringBuilder builder = new StringBuilder();
  63. string hdr1 = GetComparableForm(builder);
  64. builder.Remove(0, builder.Length);
  65. string hdr2 = hdr.GetComparableForm(builder);
  66. if (hdr1.Length != hdr2.Length)
  67. return false;
  68. if (string.CompareOrdinal(hdr1, hdr2) != 0)
  69. return false;
  70. return true;
  71. }
  72. internal string GetComparableForm()
  73. {
  74. return GetComparableForm(new StringBuilder());
  75. }
  76. internal string GetComparableForm(StringBuilder builder)
  77. {
  78. return EndpointAddressProcessor.GetComparableForm(builder, GetComparableReader());
  79. }
  80. public override int GetHashCode()
  81. {
  82. return GetComparableForm().GetHashCode();
  83. }
  84. public T GetValue<T>()
  85. {
  86. return GetValue<T>(DataContractSerializerDefaults.CreateSerializer(typeof(T), this.Name, this.Namespace, int.MaxValue/*maxItems*/));
  87. }
  88. public T GetValue<T>(XmlObjectSerializer serializer)
  89. {
  90. if (serializer == null)
  91. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
  92. using (XmlDictionaryReader reader = GetAddressHeaderReader())
  93. {
  94. if (serializer.IsStartObject(reader))
  95. return (T)serializer.ReadObject(reader);
  96. else
  97. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ExpectedElementMissing, Name, Namespace)));
  98. }
  99. }
  100. public virtual XmlDictionaryReader GetAddressHeaderReader()
  101. {
  102. XmlBuffer buffer = new XmlBuffer(int.MaxValue);
  103. XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
  104. WriteAddressHeader(writer);
  105. buffer.CloseSection();
  106. buffer.Close();
  107. return buffer.GetReader(0);
  108. }
  109. XmlDictionaryReader GetComparableReader()
  110. {
  111. XmlBuffer buffer = new XmlBuffer(int.MaxValue);
  112. XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
  113. // WSAddressingAugust2004 does not write the IsReferenceParameter attribute,
  114. // and that's good for a consistent comparable form
  115. ParameterHeader.WriteStartHeader(writer, this, AddressingVersion.WSAddressingAugust2004);
  116. ParameterHeader.WriteHeaderContents(writer, this);
  117. writer.WriteEndElement();
  118. buffer.CloseSection();
  119. buffer.Close();
  120. return buffer.GetReader(0);
  121. }
  122. protected virtual void OnWriteStartAddressHeader(XmlDictionaryWriter writer)
  123. {
  124. writer.WriteStartElement(Name, Namespace);
  125. }
  126. protected abstract void OnWriteAddressHeaderContents(XmlDictionaryWriter writer);
  127. public MessageHeader ToMessageHeader()
  128. {
  129. if (header == null)
  130. header = new ParameterHeader(this);
  131. return header;
  132. }
  133. public void WriteAddressHeader(XmlWriter writer)
  134. {
  135. WriteAddressHeader(XmlDictionaryWriter.CreateDictionaryWriter(writer));
  136. }
  137. public void WriteAddressHeader(XmlDictionaryWriter writer)
  138. {
  139. if (writer == null)
  140. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("writer"));
  141. WriteStartAddressHeader(writer);
  142. WriteAddressHeaderContents(writer);
  143. writer.WriteEndElement();
  144. }
  145. public void WriteStartAddressHeader(XmlDictionaryWriter writer)
  146. {
  147. if (writer == null)
  148. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("writer"));
  149. OnWriteStartAddressHeader(writer);
  150. }
  151. public void WriteAddressHeaderContents(XmlDictionaryWriter writer)
  152. {
  153. if (writer == null)
  154. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("writer"));
  155. OnWriteAddressHeaderContents(writer);
  156. }
  157. class ParameterHeader : MessageHeader
  158. {
  159. AddressHeader parameter;
  160. public override bool IsReferenceParameter
  161. {
  162. get { return true; }
  163. }
  164. public override string Name
  165. {
  166. get { return parameter.Name; }
  167. }
  168. public override string Namespace
  169. {
  170. get { return parameter.Namespace; }
  171. }
  172. public ParameterHeader(AddressHeader parameter)
  173. {
  174. this.parameter = parameter;
  175. }
  176. protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
  177. {
  178. if (messageVersion == null)
  179. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("messageVersion"));
  180. WriteStartHeader(writer, parameter, messageVersion.Addressing);
  181. }
  182. protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
  183. {
  184. WriteHeaderContents(writer, parameter);
  185. }
  186. internal static void WriteStartHeader(XmlDictionaryWriter writer, AddressHeader parameter, AddressingVersion addressingVersion)
  187. {
  188. parameter.WriteStartAddressHeader(writer);
  189. if (addressingVersion == AddressingVersion.WSAddressing10)
  190. {
  191. writer.WriteAttributeString(XD.AddressingDictionary.IsReferenceParameter, XD.Addressing10Dictionary.Namespace, "true");
  192. }
  193. }
  194. internal static void WriteHeaderContents(XmlDictionaryWriter writer, AddressHeader parameter)
  195. {
  196. parameter.WriteAddressHeaderContents(writer);
  197. }
  198. }
  199. class XmlObjectSerializerAddressHeader : AddressHeader
  200. {
  201. XmlObjectSerializer serializer;
  202. object objectToSerialize;
  203. string name;
  204. string ns;
  205. public XmlObjectSerializerAddressHeader(object objectToSerialize, XmlObjectSerializer serializer)
  206. {
  207. this.serializer = serializer;
  208. this.objectToSerialize = objectToSerialize;
  209. Type type = (objectToSerialize == null) ? typeof(object) : objectToSerialize.GetType();
  210. XmlQualifiedName rootName = new XsdDataContractExporter().GetRootElementName(type);
  211. this.name = rootName.Name;
  212. this.ns = rootName.Namespace;
  213. }
  214. public XmlObjectSerializerAddressHeader(string name, string ns, object objectToSerialize, XmlObjectSerializer serializer)
  215. {
  216. if ((null == name) || (name.Length == 0))
  217. {
  218. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("name"));
  219. }
  220. this.serializer = serializer;
  221. this.objectToSerialize = objectToSerialize;
  222. this.name = name;
  223. this.ns = ns;
  224. }
  225. public override string Name
  226. {
  227. get { return name; }
  228. }
  229. public override string Namespace
  230. {
  231. get { return ns; }
  232. }
  233. object ThisLock
  234. {
  235. get { return this; }
  236. }
  237. protected override void OnWriteAddressHeaderContents(XmlDictionaryWriter writer)
  238. {
  239. lock (ThisLock)
  240. {
  241. serializer.WriteObjectContent(writer, objectToSerialize);
  242. }
  243. }
  244. }
  245. // [....], This will be kept internal for now. If the optimization needs to be public, we'll re-evaluate it.
  246. class DictionaryAddressHeader : XmlObjectSerializerAddressHeader
  247. {
  248. XmlDictionaryString name;
  249. XmlDictionaryString ns;
  250. public DictionaryAddressHeader(XmlDictionaryString name, XmlDictionaryString ns, object value)
  251. : base(name.Value, ns.Value, value, DataContractSerializerDefaults.CreateSerializer(GetObjectType(value), name, ns, int.MaxValue/*maxItems*/))
  252. {
  253. this.name = name;
  254. this.ns = ns;
  255. }
  256. protected override void OnWriteStartAddressHeader(XmlDictionaryWriter writer)
  257. {
  258. writer.WriteStartElement(name, ns);
  259. }
  260. }
  261. }
  262. class BufferedAddressHeader : AddressHeader
  263. {
  264. string name;
  265. string ns;
  266. XmlBuffer buffer;
  267. bool isReferenceProperty;
  268. public BufferedAddressHeader(XmlDictionaryReader reader)
  269. {
  270. buffer = new XmlBuffer(int.MaxValue);
  271. XmlDictionaryWriter writer = buffer.OpenSection(reader.Quotas);
  272. Fx.Assert(reader.NodeType == XmlNodeType.Element, "");
  273. name = reader.LocalName;
  274. ns = reader.NamespaceURI;
  275. Fx.Assert(name != null, "");
  276. Fx.Assert(ns != null, "");
  277. writer.WriteNode(reader, false);
  278. buffer.CloseSection();
  279. buffer.Close();
  280. this.isReferenceProperty = false;
  281. }
  282. public BufferedAddressHeader(XmlDictionaryReader reader, bool isReferenceProperty)
  283. : this(reader)
  284. {
  285. this.isReferenceProperty = isReferenceProperty;
  286. }
  287. public bool IsReferencePropertyHeader { get { return this.isReferenceProperty; } }
  288. public override string Name
  289. {
  290. get { return name; }
  291. }
  292. public override string Namespace
  293. {
  294. get { return ns; }
  295. }
  296. public override XmlDictionaryReader GetAddressHeaderReader()
  297. {
  298. return buffer.GetReader(0);
  299. }
  300. protected override void OnWriteStartAddressHeader(XmlDictionaryWriter writer)
  301. {
  302. XmlDictionaryReader reader = GetAddressHeaderReader();
  303. writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
  304. writer.WriteAttributes(reader, false);
  305. reader.Close();
  306. }
  307. protected override void OnWriteAddressHeaderContents(XmlDictionaryWriter writer)
  308. {
  309. XmlDictionaryReader reader = GetAddressHeaderReader();
  310. reader.ReadStartElement();
  311. while (reader.NodeType != XmlNodeType.EndElement)
  312. writer.WriteNode(reader, false);
  313. reader.ReadEndElement();
  314. reader.Close();
  315. }
  316. }
  317. }