OletxTransactionHeader.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Transactions
  5. {
  6. using System;
  7. using System.Diagnostics;
  8. using System.ServiceModel;
  9. using System.ServiceModel.Channels;
  10. using System.Transactions;
  11. using System.Xml;
  12. using Microsoft.Transactions.Wsat.Messaging;
  13. class OleTxTransactionHeader : MessageHeader
  14. {
  15. const string OleTxHeaderElement = OleTxTransactionExternalStrings.OleTxTransaction;
  16. const string OleTxNamespace = OleTxTransactionExternalStrings.Namespace;
  17. static readonly XmlDictionaryString CoordinationNamespace = XD.CoordinationExternal10Dictionary.Namespace; // we keep using wscoor10 namespace for compatibility
  18. byte[] propagationToken;
  19. WsatExtendedInformation wsatInfo;
  20. public OleTxTransactionHeader(byte[] propagationToken, WsatExtendedInformation wsatInfo)
  21. {
  22. this.propagationToken = propagationToken;
  23. this.wsatInfo = wsatInfo;
  24. }
  25. public override bool MustUnderstand
  26. {
  27. get { return true; }
  28. }
  29. public override string Name
  30. {
  31. get { return OleTxHeaderElement; }
  32. }
  33. public override string Namespace
  34. {
  35. get { return OleTxNamespace; }
  36. }
  37. public byte[] PropagationToken
  38. {
  39. get { return this.propagationToken; }
  40. }
  41. public WsatExtendedInformation WsatExtendedInformation
  42. {
  43. get { return this.wsatInfo; }
  44. }
  45. protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
  46. {
  47. if (this.wsatInfo != null)
  48. {
  49. if (this.wsatInfo.Timeout != 0)
  50. {
  51. writer.WriteAttributeString(XD.CoordinationExternalDictionary.Expires,
  52. CoordinationNamespace,
  53. XmlConvert.ToString(this.wsatInfo.Timeout));
  54. }
  55. if (!string.IsNullOrEmpty(this.wsatInfo.Identifier))
  56. {
  57. writer.WriteAttributeString(XD.CoordinationExternalDictionary.Identifier,
  58. CoordinationNamespace,
  59. this.wsatInfo.Identifier);
  60. }
  61. }
  62. WritePropagationTokenElement(writer, this.propagationToken);
  63. }
  64. public static OleTxTransactionHeader ReadFrom(Message message)
  65. {
  66. int index;
  67. try
  68. {
  69. index = message.Headers.FindHeader(OleTxHeaderElement, OleTxNamespace);
  70. }
  71. catch (MessageHeaderException e)
  72. {
  73. DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
  74. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TransactionException(SR.GetString(SR.OleTxHeaderCorrupt), e));
  75. }
  76. if (index < 0)
  77. return null;
  78. OleTxTransactionHeader oleTxHeader;
  79. XmlDictionaryReader reader = message.Headers.GetReaderAtHeader(index);
  80. using (reader)
  81. {
  82. try
  83. {
  84. oleTxHeader = ReadFrom(reader);
  85. }
  86. catch (XmlException xe)
  87. {
  88. DiagnosticUtility.TraceHandledException(xe, TraceEventType.Error);
  89. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TransactionException(SR.GetString(SR.OleTxHeaderCorrupt), xe));
  90. }
  91. }
  92. MessageHeaderInfo header = message.Headers[index];
  93. if (!message.Headers.UnderstoodHeaders.Contains(header))
  94. {
  95. message.Headers.UnderstoodHeaders.Add(header);
  96. }
  97. return oleTxHeader;
  98. }
  99. static OleTxTransactionHeader ReadFrom(XmlDictionaryReader reader)
  100. {
  101. WsatExtendedInformation info = null;
  102. if (reader.IsStartElement(XD.OleTxTransactionExternalDictionary.OleTxTransaction,
  103. XD.OleTxTransactionExternalDictionary.Namespace))
  104. {
  105. string identifier = reader.GetAttribute(XD.CoordinationExternalDictionary.Identifier, CoordinationNamespace);
  106. if (!string.IsNullOrEmpty(identifier))
  107. {
  108. // Verify identifier is really a URI
  109. Uri uri;
  110. if (!Uri.TryCreate(identifier, UriKind.Absolute, out uri))
  111. {
  112. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidWsatExtendedInfo)));
  113. }
  114. }
  115. string attr = reader.GetAttribute(XD.CoordinationExternalDictionary.Expires, CoordinationNamespace);
  116. uint timeout = 0;
  117. if (!string.IsNullOrEmpty(attr))
  118. {
  119. try
  120. {
  121. timeout = XmlConvert.ToUInt32(attr);
  122. }
  123. catch (FormatException e)
  124. {
  125. DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
  126. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidWsatExtendedInfo), e));
  127. }
  128. catch (OverflowException e)
  129. {
  130. DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
  131. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidWsatExtendedInfo), e));
  132. }
  133. }
  134. if (!string.IsNullOrEmpty(identifier) || timeout != 0)
  135. {
  136. info = new WsatExtendedInformation(identifier, timeout);
  137. }
  138. }
  139. reader.ReadFullStartElement(XD.OleTxTransactionExternalDictionary.OleTxTransaction,
  140. XD.OleTxTransactionExternalDictionary.Namespace);
  141. byte[] propagationToken = ReadPropagationTokenElement(reader);
  142. // Skip extensibility elements...
  143. while (reader.IsStartElement())
  144. {
  145. reader.Skip();
  146. }
  147. reader.ReadEndElement();
  148. return new OleTxTransactionHeader(propagationToken, info);
  149. }
  150. public static void WritePropagationTokenElement(XmlDictionaryWriter writer, byte[] propagationToken)
  151. {
  152. writer.WriteStartElement(XD.OleTxTransactionExternalDictionary.PropagationToken,
  153. XD.OleTxTransactionExternalDictionary.Namespace);
  154. writer.WriteBase64(propagationToken, 0, propagationToken.Length);
  155. writer.WriteEndElement();
  156. }
  157. public static bool IsStartPropagationTokenElement(XmlDictionaryReader reader)
  158. {
  159. return reader.IsStartElement(XD.OleTxTransactionExternalDictionary.PropagationToken,
  160. XD.OleTxTransactionExternalDictionary.Namespace);
  161. }
  162. public static byte[] ReadPropagationTokenElement(XmlDictionaryReader reader)
  163. {
  164. reader.ReadFullStartElement(XD.OleTxTransactionExternalDictionary.PropagationToken,
  165. XD.OleTxTransactionExternalDictionary.Namespace);
  166. byte[] propagationToken = reader.ReadContentAsBase64();
  167. if (propagationToken.Length == 0)
  168. {
  169. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidPropagationToken)));
  170. }
  171. reader.ReadEndElement();
  172. return propagationToken;
  173. }
  174. }
  175. }