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