| File: FrameworkFork\System.ServiceModel\System\ServiceModel\Channels\TransactionFlowBindingElement.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. namespace System.ServiceModel.Channels { using System; using System.ServiceModel.Description; using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Security; using System.ComponentModel; //using System.ServiceModel.Transactions; using Microsoft.Xml; public sealed class TransactionFlowBindingElement : BindingElement { private bool _transactions; private TransactionFlowOption _issuedTokens; private TransactionProtocol _transactionProtocol; public TransactionFlowBindingElement() : this(true, TransactionFlowDefaults.TransactionProtocol) { } public TransactionFlowBindingElement(TransactionProtocol transactionProtocol) : this(true, transactionProtocol) { } internal TransactionFlowBindingElement(bool transactions) : this(transactions, TransactionFlowDefaults.TransactionProtocol) { } internal TransactionFlowBindingElement(bool transactions, TransactionProtocol transactionProtocol) { _transactions = transactions; _issuedTokens = transactions ? TransactionFlowOption.Allowed : TransactionFlowOption.NotAllowed; if (!TransactionProtocol.IsDefined(transactionProtocol)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(string.Format(SRServiceModel.ConfigInvalidTransactionFlowProtocolValue, transactionProtocol.ToString())); } _transactionProtocol = transactionProtocol; } private TransactionFlowBindingElement(TransactionFlowBindingElement elementToBeCloned) : base(elementToBeCloned) { _transactions = elementToBeCloned._transactions; _issuedTokens = elementToBeCloned._issuedTokens; if (!TransactionProtocol.IsDefined(elementToBeCloned._transactionProtocol)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(string.Format(SRServiceModel.ConfigInvalidTransactionFlowProtocolValue, elementToBeCloned._transactionProtocol.ToString())); } _transactionProtocol = elementToBeCloned._transactionProtocol; this.AllowWildcardAction = elementToBeCloned.AllowWildcardAction; } internal bool Transactions { get { return _transactions; } set { _transactions = value; _issuedTokens = value ? TransactionFlowOption.Allowed : TransactionFlowOption.NotAllowed; } } internal TransactionFlowOption IssuedTokens { get { return _issuedTokens; } set { ValidateOption(value); _issuedTokens = value; } } public override BindingElement Clone() { return new TransactionFlowBindingElement(this); } private bool IsFlowEnabled(Dictionary<DirectionalAction, TransactionFlowOption> dictionary) { if (_issuedTokens != TransactionFlowOption.NotAllowed) { return true; } if (!_transactions) { return false; } foreach (TransactionFlowOption option in dictionary.Values) { if (option != TransactionFlowOption.NotAllowed) { return true; } } return false; } internal bool IsFlowEnabled(ContractDescription contract) { if (_issuedTokens != TransactionFlowOption.NotAllowed) { return true; } if (!_transactions) { return false; } foreach (OperationDescription operation in contract.Operations) { TransactionFlowAttribute parameter = operation.Behaviors.Find<TransactionFlowAttribute>(); if (parameter != null) { if (parameter.Transactions != TransactionFlowOption.NotAllowed) { return true; } } } return false; } public TransactionProtocol TransactionProtocol { get { return _transactionProtocol; } set { if (!TransactionProtocol.IsDefined(value)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value")); _transactionProtocol = value; } } [DefaultValue(false)] public bool AllowWildcardAction { get; set; } internal static void ValidateOption(TransactionFlowOption opt) { if (!TransactionFlowOptionHelper.IsDefined(opt)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRServiceModel.TransactionFlowBadOption))); } [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeTransactionProtocol() { return this.TransactionProtocol != TransactionProtocol.Default; } public override bool CanBuildChannelFactory<TChannel>(BindingContext context) { if (context == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("context")); } if (typeof(TChannel) == typeof(IOutputChannel) || typeof(TChannel) == typeof(IDuplexChannel) || typeof(TChannel) == typeof(IRequestChannel) || typeof(TChannel) == typeof(IOutputSessionChannel) || typeof(TChannel) == typeof(IRequestSessionChannel) || typeof(TChannel) == typeof(IDuplexSessionChannel)) { return context.CanBuildInnerChannelFactory<TChannel>(); } return false; } private Dictionary<DirectionalAction, TransactionFlowOption> GetDictionary(BindingContext context) { Dictionary<DirectionalAction, TransactionFlowOption> dictionary = context.BindingParameters.Find<Dictionary<DirectionalAction, TransactionFlowOption>>(); if (dictionary == null) dictionary = new Dictionary<DirectionalAction, TransactionFlowOption>(); return dictionary; } internal static MessagePartSpecification GetIssuedTokenHeaderSpecification(SecurityStandardsManager standardsManager) { MessagePartSpecification result; if (standardsManager.TrustDriver.IsIssuedTokensSupported) result = new MessagePartSpecification(new XmlQualifiedName(standardsManager.TrustDriver.IssuedTokensHeaderName, standardsManager.TrustDriver.IssuedTokensHeaderNamespace)); else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRServiceModel.TrustDriverVersionDoesNotSupportIssuedTokens))); } return result; } public override T GetProperty<T>(BindingContext context) { if (typeof(T) == typeof(ChannelProtectionRequirements)) { ChannelProtectionRequirements myRequirements = this.GetProtectionRequirements(); if (myRequirements != null) { myRequirements.Add(context.GetInnerProperty<ChannelProtectionRequirements>() ?? new ChannelProtectionRequirements()); return (T)(object)myRequirements; } else { return (T)(object)context.GetInnerProperty<ChannelProtectionRequirements>(); } } else { return context.GetInnerProperty<T>(); } } private ChannelProtectionRequirements GetProtectionRequirements() { if (this.Transactions || (this.IssuedTokens != TransactionFlowOption.NotAllowed)) { ChannelProtectionRequirements requirements = new ChannelProtectionRequirements(); if (this.Transactions) { MessagePartSpecification p = new MessagePartSpecification( new XmlQualifiedName(CoordinationExternalStrings.CoordinationContext, CoordinationExternal10Strings.Namespace), new XmlQualifiedName(CoordinationExternalStrings.CoordinationContext, CoordinationExternal11Strings.Namespace), new XmlQualifiedName(OleTxTransactionExternalStrings.OleTxTransaction, OleTxTransactionExternalStrings.Namespace)); p.MakeReadOnly(); requirements.IncomingSignatureParts.AddParts(p); requirements.OutgoingSignatureParts.AddParts(p); requirements.IncomingEncryptionParts.AddParts(p); requirements.OutgoingEncryptionParts.AddParts(p); } if (this.IssuedTokens != TransactionFlowOption.NotAllowed) { MessagePartSpecification trustParts = GetIssuedTokenHeaderSpecification(SecurityStandardsManager.DefaultInstance); trustParts.MakeReadOnly(); requirements.IncomingSignatureParts.AddParts(trustParts); requirements.IncomingEncryptionParts.AddParts(trustParts); requirements.OutgoingSignatureParts.AddParts(trustParts); requirements.OutgoingEncryptionParts.AddParts(trustParts); } MessagePartSpecification body = new MessagePartSpecification(true); body.MakeReadOnly(); requirements.OutgoingSignatureParts.AddParts(body, FaultCodeConstants.Actions.Transactions); requirements.OutgoingEncryptionParts.AddParts(body, FaultCodeConstants.Actions.Transactions); return requirements; } else { return null; } } private XmlElement GetAssertion(XmlDocument doc, TransactionFlowOption option, string prefix, string name, string ns, string policyNs) { if (doc == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("doc"); XmlElement result = null; switch (option) { case TransactionFlowOption.NotAllowed: // Don't generate an assertion break; case TransactionFlowOption.Allowed: result = doc.CreateElement(prefix, name, ns); // Always insert the real wsp:Optional attribute XmlAttribute attr = doc.CreateAttribute(TransactionPolicyStrings.OptionalPrefix11, TransactionPolicyStrings.OptionalLocal, policyNs); attr.Value = TransactionPolicyStrings.TrueValue; result.Attributes.Append(attr); // For legacy protocols, also insert the legacy attribute for backward compat if (_transactionProtocol == TransactionProtocol.OleTransactions || _transactionProtocol == TransactionProtocol.WSAtomicTransactionOctober2004) { XmlAttribute attrLegacy = doc.CreateAttribute(TransactionPolicyStrings.OptionalPrefix10, TransactionPolicyStrings.OptionalLocal, TransactionPolicyStrings.OptionalNamespaceLegacy); attrLegacy.Value = TransactionPolicyStrings.TrueValue; result.Attributes.Append(attrLegacy); } break; case TransactionFlowOption.Mandatory: result = doc.CreateElement(prefix, name, ns); break; } return result; } internal override bool IsMatch(BindingElement b) { if (b == null) return false; TransactionFlowBindingElement txFlow = b as TransactionFlowBindingElement; if (txFlow == null) return false; if (_transactions != txFlow._transactions) return false; if (_issuedTokens != txFlow._issuedTokens) return false; if (_transactionProtocol != txFlow._transactionProtocol) return false; return true; } } }