TransactionFlowBindingElement.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / TransactionFlowBindingElement.cs / 1 / TransactionFlowBindingElement.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
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.ServiceModel.Transactions;
    using System.Xml; 

    public sealed class TransactionFlowBindingElement : BindingElement, IPolicyExportExtension 
    { 
        bool transactions;
        TransactionFlowOption issuedTokens; 
        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) 
        {
            this.transactions = transactions;
            this.issuedTokens = transactions ? TransactionFlowOption.Allowed : TransactionFlowOption.NotAllowed;
 
            if (!TransactionProtocol.IsDefined(transactionProtocol))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.ConfigInvalidTransactionFlowProtocolValue, transactionProtocol.ToString())); 
            }
 
            this.transactionProtocol = transactionProtocol;
        }

        TransactionFlowBindingElement(TransactionFlowBindingElement elementToBeCloned) 
            : base(elementToBeCloned)
        { 
            this.transactions = elementToBeCloned.transactions; 
            this.issuedTokens = elementToBeCloned.issuedTokens;
 
            if (!TransactionProtocol.IsDefined(elementToBeCloned.transactionProtocol))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.ConfigInvalidTransactionFlowProtocolValue, elementToBeCloned.transactionProtocol.ToString()));
            } 

            this.transactionProtocol = elementToBeCloned.transactionProtocol; 
        } 

        internal bool Transactions 
        {
            get
            {
                return this.transactions; 
            }
            set 
            { 
                this.transactions = value;
                this.issuedTokens = value ? TransactionFlowOption.Allowed : TransactionFlowOption.NotAllowed; 
            }
        }

        internal TransactionFlowOption IssuedTokens 
        {
            get 
            { 
                return this.issuedTokens;
            } 
            set
            {
                ValidateOption(value);
                this.issuedTokens = value; 
            }
        } 
 
        public override BindingElement Clone()
        { 
            return new TransactionFlowBindingElement(this);
        }

        bool IsFlowEnabled(Dictionary dictionary) 
        {
            if (this.issuedTokens != TransactionFlowOption.NotAllowed) 
            { 
                return true;
            } 

            if (!this.transactions)
            {
                return false; 
            }
 
            foreach (TransactionFlowOption option in dictionary.Values) 
            {
                if (option != TransactionFlowOption.NotAllowed) 
                {
                    return true;
                }
            } 

            return false; 
        } 

        internal bool IsFlowEnabled(ContractDescription contract) 
        {
            if (this.issuedTokens != TransactionFlowOption.NotAllowed)
            {
                return true; 
            }
 
            if (!this.transactions) 
            {
                return false; 
            }

            foreach (OperationDescription operation in contract.Operations)
            { 
                TransactionFlowAttribute parameter = operation.Behaviors.Find();
                if (parameter != null) 
                { 
                    if (parameter.Transactions != TransactionFlowOption.NotAllowed)
                    { 
                        return true;
                    }
                }
            } 

            return false; 
        } 

        public TransactionProtocol TransactionProtocol 
        {
            get
            {
                return this.transactionProtocol; 
            }
            set 
            { 
                if (!TransactionProtocol.IsDefined(value))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value")); 
                this.transactionProtocol = value;
            }
        }
 
        internal static void ValidateOption(TransactionFlowOption opt)
        { 
            if (!TransactionFlowOptionHelper.IsDefined(opt)) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.TransactionFlowBadOption)));
        } 

        public override bool CanBuildChannelFactory(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(); 
            }
 
            return false;
        }

        // The BuildChannelFactory and BuildListenerFactory methods looks for this BindingParameter 
        // in the BindingContext:
        //  - Dictionary 
        // which has the per-operation TransactionFlowOptions 
        public override IChannelFactory BuildChannelFactory(BindingContext context)
        { 
            if (context == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
            } 

            if (!this.CanBuildChannelFactory(context)) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TChannel", SR.GetString(SR.ChannelTypeNotSupported, typeof(TChannel)));
            } 

            Dictionary dictionary = GetDictionary(context);

            if (!this.IsFlowEnabled(dictionary)) 
            {
                return context.BuildInnerChannelFactory(); 
            } 

            if (this.issuedTokens == TransactionFlowOption.NotAllowed) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TransactionFlowRequiredIssuedTokens)));
            }
 
            TransactionChannelFactory channelFactory =
                new TransactionChannelFactory(this.transactionProtocol, context, dictionary); 
 
            channelFactory.FlowIssuedTokens = this.IssuedTokens;
 
            return channelFactory;
        }

        public override IChannelListener BuildChannelListener(BindingContext context) 
        {
            if (context == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("context"));
            } 

            if (!context.CanBuildInnerChannelListener())
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TChannel", SR.GetString(SR.ChannelTypeNotSupported, typeof(TChannel))); 
            }
 
            Dictionary dictionary = GetDictionary(context); 

            if (!this.IsFlowEnabled(dictionary)) 
            {
                return context.BuildInnerChannelListener();
            }
 
            if (this.issuedTokens == TransactionFlowOption.NotAllowed)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TransactionFlowRequiredIssuedTokens))); 
            }
 
            IChannelListener innerListener = context.BuildInnerChannelListener();
            TransactionChannelListener listener = new TransactionChannelListener(this.transactionProtocol, context.Binding, dictionary, innerListener);

            listener.FlowIssuedTokens = this.IssuedTokens; 

            return listener; 
        } 

        public override bool CanBuildChannelListener(BindingContext context) 
        {
            if (!context.CanBuildInnerChannelListener())
                return false;
 
            return (typeof(TChannel) == typeof(IInputChannel) ||
                    typeof(TChannel) == typeof(IReplyChannel) || 
                    typeof(TChannel) == typeof(IDuplexChannel) || 
                    typeof(TChannel) == typeof(IInputSessionChannel) ||
                    typeof(TChannel) == typeof(IReplySessionChannel) || 
                    typeof(TChannel) == typeof(IDuplexSessionChannel));
        }

        Dictionary GetDictionary(BindingContext context) 
        {
            Dictionary dictionary = 
                context.BindingParameters.Find>(); 
            if (dictionary == null)
                dictionary = new Dictionary(); 
            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(SR.GetString(SR.TrustDriverVersionDoesNotSupportIssuedTokens)));
            } 

            return result; 
        } 

        public override T GetProperty(BindingContext context) 
        {
            if (typeof(T) == typeof(ChannelProtectionRequirements))
            {
                ChannelProtectionRequirements myRequirements = this.GetProtectionRequirements(); 
                if (myRequirements != null)
                { 
                    myRequirements.Add(context.GetInnerProperty() ?? new ChannelProtectionRequirements()); 
                    return (T)(object)myRequirements;
                } 
                else
                {
                    return (T)(object)context.GetInnerProperty();
                } 
            }
            else 
            { 
                return context.GetInnerProperty();
            } 
        }

        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;
            }
        } 

        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 (this.transactionProtocol == TransactionProtocol.OleTransactions ||
                        this.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; 
        } 

        void IPolicyExportExtension.ExportPolicy(MetadataExporter exporter, PolicyConversionContext context) 
        {
            if (exporter == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("exporter"); 
            }
            if (context == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
            } 

            TransactionFlowBindingElement bindingElement = context.BindingElements.Find();
            if (bindingElement == null || !bindingElement.Transactions)
                return; 

            XmlDocument doc = new XmlDocument(); 
            XmlElement assertion = null; 

            foreach (OperationDescription operation in context.Contract.Operations) 
            {
                TransactionFlowAttribute contextParam = operation.Behaviors.Find();
                TransactionFlowOption txFlowOption = contextParam == null ? TransactionFlowOption.NotAllowed : contextParam.Transactions;
 
                // Transactions
                if (bindingElement.TransactionProtocol == TransactionProtocol.OleTransactions) 
                { 
                    assertion = GetAssertion(doc, txFlowOption,
                                         TransactionPolicyStrings.OleTxTransactionsPrefix, TransactionPolicyStrings.OleTxTransactionsLocal, 
                                         TransactionPolicyStrings.OleTxTransactionsNamespace, exporter.PolicyVersion.Namespace);
                }
                else if (bindingElement.TransactionProtocol == TransactionProtocol.WSAtomicTransactionOctober2004)
                { 
                    assertion = GetAssertion(doc, txFlowOption,
                                         TransactionPolicyStrings.WsatTransactionsPrefix, TransactionPolicyStrings.WsatTransactionsLocal, 
                                         TransactionPolicyStrings.WsatTransactionsNamespace10, exporter.PolicyVersion.Namespace); 
                }
                else if (bindingElement.TransactionProtocol == TransactionProtocol.WSAtomicTransaction11) 
                {
                    assertion = GetAssertion(doc, txFlowOption,
                                         TransactionPolicyStrings.WsatTransactionsPrefix, TransactionPolicyStrings.WsatTransactionsLocal,
                                         TransactionPolicyStrings.WsatTransactionsNamespace11, exporter.PolicyVersion.Namespace); 
                }
 
                if (assertion != null) 
                    context.GetOperationBindingAssertions(operation).Add(assertion);
            } 

        }

        internal override bool IsMatch(BindingElement b) 
        {
            if (b == null) 
                return false; 
            TransactionFlowBindingElement txFlow = b as TransactionFlowBindingElement;
            if (txFlow == null) 
                return false;
            if (this.transactions != txFlow.transactions)
                return false;
            if (this.issuedTokens != txFlow.issuedTokens) 
                return false;
            if (this.transactionProtocol != txFlow.transactionProtocol) 
                return false; 

            return true; 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK