File: System\ServiceModel\Channels\TransactionFlowProperty.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.Channels
{
    using System;
    using System.Collections.Generic;
    using System.ServiceModel;
    using System.ServiceModel.Security;
 
    using System.Transactions;
    using System.Runtime.Remoting.Messaging;
    using System.ServiceModel.Transactions;
    using System.ServiceModel.Diagnostics;
 
    sealed public class TransactionMessageProperty
    {
        TransactionInfo flowedTransactionInfo;
        Transaction flowedTransaction;
        const string PropertyName = "TransactionMessageProperty";
 
        private TransactionMessageProperty()
        {
        }
 
        public Transaction Transaction
        {
            get
            {
                if (this.flowedTransaction == null && this.flowedTransactionInfo != null)
                {
                    try
                    {
                        this.flowedTransaction = this.flowedTransactionInfo.UnmarshalTransaction();
                    }
                    catch (TransactionException e)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
                    }
                }
                return this.flowedTransaction;
            }
        }
 
        static internal TransactionMessageProperty TryGet(Message message)
        {
            if (message.Properties.ContainsKey(PropertyName))
                return message.Properties[PropertyName] as TransactionMessageProperty;
            else
                return null;
        }
 
        static internal Transaction TryGetTransaction(Message message)
        {
            if (!message.Properties.ContainsKey(PropertyName))
                return null;
 
            return ((TransactionMessageProperty)message.Properties[PropertyName]).Transaction;
 
        }
 
        static TransactionMessageProperty GetPropertyAndThrowIfAlreadySet(Message message)
        {
            if (message.Properties.ContainsKey(PropertyName))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new FaultException(SR.GetString(SR.SFxTryAddMultipleTransactionsOnMessage)));
            }
 
            return new TransactionMessageProperty();
        }
 
        static public void Set(Transaction transaction, Message message)
        {
            TransactionMessageProperty property = GetPropertyAndThrowIfAlreadySet(message);
            property.flowedTransaction = transaction;
            message.Properties.Add(PropertyName, property);
        }
 
        static internal void Set(TransactionInfo transactionInfo, Message message)
        {
            TransactionMessageProperty property = GetPropertyAndThrowIfAlreadySet(message);
            property.flowedTransactionInfo = transactionInfo;
            message.Properties.Add(PropertyName, property);
        }
    }
 
 
 
    class TransactionFlowProperty
    {
        Transaction flowedTransaction;
        List<RequestSecurityTokenResponse> issuedTokens;
        const string PropertyName = "TransactionFlowProperty";
 
        private TransactionFlowProperty()
        {
        }
 
        internal ICollection<RequestSecurityTokenResponse> IssuedTokens
        {
            get
            {
                if (this.issuedTokens == null)
                {
                    this.issuedTokens = new List<RequestSecurityTokenResponse>();
                }
 
                return this.issuedTokens;
            }
        }
 
        internal Transaction Transaction
        {
            get { return this.flowedTransaction; }
        }
 
        static internal TransactionFlowProperty Ensure(Message message)
        {
            if (message.Properties.ContainsKey(PropertyName))
                return (TransactionFlowProperty)message.Properties[PropertyName];
 
            TransactionFlowProperty property = new TransactionFlowProperty();
            message.Properties.Add(PropertyName, property);
            return property;
        }
 
        static internal TransactionFlowProperty TryGet(Message message)
        {
            if (message.Properties.ContainsKey(PropertyName))
                return message.Properties[PropertyName] as TransactionFlowProperty;
            else
                return null;
        }
 
        static internal ICollection<RequestSecurityTokenResponse> TryGetIssuedTokens(Message message)
        {
            TransactionFlowProperty property = TransactionFlowProperty.TryGet(message);
            if (property == null)
                return null;
 
            // use this when reading only, consistently return null if no tokens.
            if (property.issuedTokens == null || property.issuedTokens.Count == 0)
                return null;
 
            return property.issuedTokens;
        }
 
        static internal Transaction TryGetTransaction(Message message)
        {
            if (!message.Properties.ContainsKey(PropertyName))
                return null;
 
            return ((TransactionFlowProperty)message.Properties[PropertyName]).Transaction;
 
        }
 
        static TransactionFlowProperty GetPropertyAndThrowIfAlreadySet(Message message)
        {
            TransactionFlowProperty property = TryGet(message);
 
            if (property != null)
            {
                if (property.flowedTransaction != null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FaultException(SR.GetString(SR.SFxTryAddMultipleTransactionsOnMessage)));
                }
            }
            else
            {
                property = new TransactionFlowProperty();
            }
 
            return property;
        }
 
        static internal void Set(Transaction transaction, Message message)
        {
            TransactionFlowProperty property = GetPropertyAndThrowIfAlreadySet(message);
            property.flowedTransaction = transaction;
            message.Properties.Add(PropertyName, property);
        }
    }
}