File: System\Workflow\Activities\ReceiveActivity.cs
Project: ndp\cdf\src\NetFx35\System.WorkflowServices\System.WorkflowServices.csproj (System.WorkflowServices)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
namespace System.Workflow.Activities
{
    using System;
    using System.Reflection;
    using System.Collections;
    using System.Collections.ObjectModel;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Drawing;
    using System.Globalization;
    using System.IdentityModel.Claims;
    using System.Security.Permissions;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    using System.Workflow.Activities;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Compiler;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.ComponentModel.Serialization;
    using System.Workflow.Runtime;
    using System.Xml;
 
    [SR2Description(SR2DescriptionAttribute.ReceiveActivityDescription)]
    [SR2Category(SR2CategoryAttribute.Standard)]
    [Designer(typeof(ReceiveActivityDesigner), typeof(IDesigner))]
    [ToolboxBitmap(typeof(ReceiveActivity), "Design.Resources.ReceiveActivity.png")]
    [ActivityValidator(typeof(ReceiveActivityValidator))]
    [Serializable]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class ReceiveActivity : SequenceActivity,
        IEventActivity,
        IActivityEventListener<QueueEventArgs>,
        IServiceDescriptionBuilder
    {
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        public static readonly DependencyProperty FaultMessageProperty =
            DependencyProperty.Register("FaultMessage",
            typeof(FaultException),
            typeof(ReceiveActivity),
            new PropertyMetadata(null));
 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        public static readonly DependencyProperty OperationValidationEvent =
            DependencyProperty.Register("OperationValidation",
            typeof(EventHandler<OperationValidationEventArgs>),
            typeof(ReceiveActivity));
 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        public static readonly DependencyProperty WorkflowServiceAttributesProperty =
            DependencyProperty.RegisterAttached("WorkflowServiceAttributes",
            typeof(WorkflowServiceAttributes), typeof(ReceiveActivity),
            new PropertyMetadata(null, DependencyPropertyOptions.Metadata,
            ReceiveActivity.GetWorkflowServiceAttributesValueOverride, null),
            typeof(WorkflowServiceAttributesDynamicPropertyValidator));
 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        internal static readonly DependencyProperty CanCreateInstanceProperty =
            DependencyProperty.Register("CanCreateInstance",
            typeof(bool),
            typeof(ReceiveActivity),
            new PropertyMetadata(false, DependencyPropertyOptions.Metadata));
 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        internal static readonly DependencyProperty ContextTokenProperty =
            DependencyProperty.Register("ContextToken",
            typeof(ContextToken),
            typeof(ReceiveActivity),
            new PropertyMetadata(null, DependencyPropertyOptions.Metadata));
 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        internal static readonly DependencyProperty ParameterBindingsProperty =
            DependencyProperty.Register("ParameterBindings",
            typeof(WorkflowParameterBindingCollection),
            typeof(ReceiveActivity),
            new PropertyMetadata(DependencyPropertyOptions.Metadata | DependencyPropertyOptions.ReadOnly));
 
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        internal static readonly DependencyProperty ServiceOperationInfoProperty =
            DependencyProperty.Register("ServiceOperationInfo",
            typeof(OperationInfoBase),
            typeof(ReceiveActivity),
            new PropertyMetadata(DependencyPropertyOptions.Metadata));
 
        private static readonly DependencyProperty QueueNameProperty =
            DependencyProperty.Register("QueueName",
            typeof(string),
            typeof(ReceiveActivity));
 
        private static readonly DependencyProperty RequestContextProperty =
            DependencyProperty.Register("RequestContext",
            typeof(WorkflowRequestContext),
            typeof(ReceiveActivity));
 
        static DependencyProperty QueueInitializationModeProperty =
            DependencyProperty.Register("QueueInitializationMode",
            typeof(QueueInitializationMode),
            typeof(ReceiveActivity),
            new PropertyMetadata(QueueInitializationMode.Standalone));
 
        [NonSerialized]
        private ReceiveOperationInfoHelper operationHelper;
 
        private IActivityEventListener<QueueEventArgs> securityShim;
        private IActivityEventListener<QueueEventArgs> validationShim;
 
        [NonSerialized]
        private static Hashtable requestContextsCache = Hashtable.Synchronized(new Hashtable());
        private bool isContextCached;
 
        public ReceiveActivity()
        {
            base.SetReadOnlyPropertyValue(ReceiveActivity.ParameterBindingsProperty,
                new WorkflowParameterBindingCollection(this));
        }
 
        public ReceiveActivity(string name)
            : base(name)
        {
            base.SetReadOnlyPropertyValue(ReceiveActivity.ParameterBindingsProperty,
                new WorkflowParameterBindingCollection(this));
        }
 
        [SRCategory(SR2CategoryAttribute.Handlers)]
        [SR2Description(SR2DescriptionAttribute.Receive_OperationValidation_Description)]
        [MergableProperty(false)]
        public event EventHandler<OperationValidationEventArgs> OperationValidation
        {
            add
            {
                base.AddHandler(OperationValidationEvent, value);
            }
            remove
            {
                base.RemoveHandler(OperationValidationEvent, value);
            }
        }
 
        [Browsable(true)]
        [DefaultValue(false)]
        [SR2Category(SR2CategoryAttribute.Activity)]
        [SR2Description(SR2DescriptionAttribute.Receive_CanCreateInstance_Description)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public bool CanCreateInstance
        {
            get
            {
                return ((bool)(base.GetValue(ReceiveActivity.CanCreateInstanceProperty)));
            }
            set
            {
                base.SetValue(ReceiveActivity.CanCreateInstanceProperty, value);
            }
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IDictionary<string, string> Context
        {
            get
            {
                if (this.ContextToken == null)
                {
                    return ReceiveActivity.GetRootContext(this);
                }
                return ReceiveActivity.GetContext(this, this.ContextToken);
            }
        }
 
        [DefaultValue(null)]
        [MergableProperty(false)]
        [RefreshProperties(RefreshProperties.All)]
        [SR2Category(SR2CategoryAttribute.Activity)]
        [SR2Description(SR2DescriptionAttribute.Receive_ContextToken_Description)]
        [TypeConverter(typeof(ContextTokenTypeConverter))]
        public ContextToken ContextToken
        {
            get
            {
                return base.GetValue(ContextTokenProperty) as ContextToken;
            }
            set
            {
                base.SetValue(ContextTokenProperty, value);
            }
        }
 
        [Browsable(true)]
        [DefaultValue(null)]
        [SR2Category(SR2CategoryAttribute.Activity)]
        [SR2Description(SR2DescriptionAttribute.Receive_FaultMessage_Description)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public FaultException FaultMessage
        {
            get
            {
                return ((FaultException)base.GetValue(ReceiveActivity.FaultMessageProperty));
            }
 
            set
            {
                base.SetValue(ReceiveActivity.FaultMessageProperty, value);
            }
        }
 
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public WorkflowParameterBindingCollection ParameterBindings
        {
            get
            {
                return ((WorkflowParameterBindingCollection)(base.GetValue(ReceiveActivity.ParameterBindingsProperty)));
            }
        }
 
 
        [Browsable(true)]
        [SR2Category(SR2CategoryAttribute.Activity)]
        [SR2Description(SR2DescriptionAttribute.Receive_OperationInfo_Description)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public OperationInfoBase ServiceOperationInfo
        {
            get
            {
                return ((OperationInfoBase)(base.GetValue(ReceiveActivity.ServiceOperationInfoProperty)));
            }
            set
            {
                OperationInfoBase currentValue = ((OperationInfoBase)(base.GetValue(ReceiveActivity.ServiceOperationInfoProperty)));
                if (value != null && currentValue != value)
                {
                    DependencyProperty ParentDependencyObjectProperty =
                        DependencyProperty.FromName("ParentDependencyObject", typeof(DependencyObject));
 
                    Activity currentParent = value.GetValue(ParentDependencyObjectProperty) as Activity;
 
                    if (currentParent != null)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                            "value",
                            SR2.GetString(SR2.Error_OperationIsAlreadyAssociatedWithActivity,
                            value,
                            currentParent.QualifiedName));
                    }
 
                    if (currentValue != null)
                    {
                        currentValue.SetValue(ParentDependencyObjectProperty, null);
                    }
 
                    value.SetValue(ParentDependencyObjectProperty, this);
                }
 
                if (this.DesignMode && value is OperationInfo)
                {
                    Activity rootActivity = this.RootActivity;
                    rootActivity.RemoveProperty(DynamicContractTypeBuilder.DynamicContractTypesProperty);
                }
 
                base.SetValue(ReceiveActivity.ServiceOperationInfoProperty, value);
            }
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        internal WorkflowRequestContext RequestContext
        {
            get
            {
                return ((WorkflowRequestContext)(base.GetValue(ReceiveActivity.RequestContextProperty)));
            }
            set
            {
                base.SetValue(ReceiveActivity.RequestContextProperty, value);
            }
        }
 
        IComparable IEventActivity.QueueName
        {
            get { return this.GetValue(ReceiveActivity.QueueNameProperty) as string; }
        }
 
        ReceiveOperationInfoHelper OperationHelper
        {
            get
            {
                if (this.operationHelper == null)
                {
                    if (this.UserData.Contains(typeof(ReceiveOperationInfoHelper)))
                    {
                        this.operationHelper = this.UserData[typeof(ReceiveOperationInfoHelper)] as ReceiveOperationInfoHelper;
                    }
                }
 
                if (this.operationHelper == null)
                {
                    this.operationHelper = new ReceiveOperationInfoHelper(this.Site, this);
                    this.UserData[typeof(ReceiveOperationInfoHelper)] = this.operationHelper;
                }
 
                return this.operationHelper;
            }
        }
 
        private QueueInitializationMode QueueInitializationMode
        {
            get
            {
                return (QueueInitializationMode)base.GetValue(ReceiveActivity.QueueInitializationModeProperty);
            }
            set
            {
                base.SetValue(ReceiveActivity.QueueInitializationModeProperty, value);
            }
        }
 
        public static IDictionary<string, string> GetContext(Activity activity,
            ContextToken contextToken)
        {
            if (activity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
            }
            if (contextToken == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextToken");
            }
 
            if (contextToken.IsRootContext)
            {
                return GetRootContext(activity);
            }
 
            return GetContext(activity, contextToken.Name, contextToken.OwnerActivityName);
        }
 
        public static IDictionary<string, string> GetContext(Activity activity,
            string contextName,
            string ownerActivityName)
        {
            if (activity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
            }
            if (string.IsNullOrEmpty(contextName))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("contextName",
                    SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
            }
 
            ReceiveContext receiveContext = ContextToken.GetReceiveContext(activity, contextName, ownerActivityName);
            if (receiveContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_CannotFindReceiveContext, contextName)));
            }
 
            return receiveContext.Properties;
        }
 
        public static IDictionary<string, string> GetRootContext(Activity activity)
        {
            if (activity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
            }
 
            ReceiveContext receiveContext = ContextToken.GetRootReceiveContext(activity);
            if (receiveContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_CannotFindReceiveContext, ContextToken.RootContextName)));
            }
 
            return receiveContext.Properties;
        }
 
        public static object GetWorkflowServiceAttributes(object dependencyObject)
        {
            if (dependencyObject == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dependencyObject");
            }
            if (!(dependencyObject is Activity))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                    "dependencyObject",
                    SR2.GetString(SR2.Error_UnexpectedArgumentType, typeof(Activity).FullName));
            }
 
            return (dependencyObject as DependencyObject).GetValue(ReceiveActivity.WorkflowServiceAttributesProperty);
        }
 
        public static void SetWorkflowServiceAttributes(object dependencyObject,
            object value)
        {
            if (dependencyObject == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dependencyObject");
            }
            if (!(dependencyObject is Activity))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                    "dependencyObject",
                    SR2.GetString(SR2.Error_UnexpectedArgumentType, typeof(Activity).FullName));
            }
 
            (dependencyObject as DependencyObject).SetValue(ReceiveActivity.WorkflowServiceAttributesProperty, value);
        }
 
        void IActivityEventListener<QueueEventArgs>.OnEvent(object sender,
            QueueEventArgs e)
        {
            if (sender == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sender");
            }
 
            if (e == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("e");
            }
 
            ActivityExecutionContext executionContext = sender as ActivityExecutionContext;
            if (executionContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentException(SR2.GetString(SR2.Error_ArgumentTypeInvalid,
                    "sender",
                    typeof(ActivityExecutionContext))));
            }
 
            WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
            if (queuingService == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
                    typeof(WorkflowQueuingService))));
            }
 
            WorkflowQueue workflowQueue = queuingService.GetWorkflowQueue(e.QueueName);
            if (workflowQueue == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound, e.QueueName)));
            }
 
            if (workflowQueue.Count != 0)
            {
                WorkflowRequestContext requestContext = workflowQueue.Peek() as WorkflowRequestContext;
                if (requestContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
                        this.QualifiedName)));
                }
                if (ValidationShim.EvaluateSecurityConstraints(executionContext, this, requestContext))
                {
                    workflowQueue.UnregisterForQueueItemAvailable(this);
                    this.RequestContext = workflowQueue.Dequeue() as WorkflowRequestContext;
                    CacheRequestContext(this.RequestContext);
 
                    if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
                    {
                        if (this.securityShim != null)
                        {
                            workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
                            this.securityShim = null;
                        }
                        workflowQueue.Enabled = false;
                    }
 
                    if (this.RequestContext == null)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable, this.QualifiedName)));
                    }
 
                    if (ExecuteActivity(this.RequestContext, executionContext) == ActivityExecutionStatus.Closed)
                    {
                        try
                        {
                            executionContext.CloseActivity();
                        }
                        finally
                        {
                            RemoveRequestContext();
                        }
                    }
                }
                else
                {
                    workflowQueue.Dequeue();
 
                    try
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                            "Workflow Instance {0}, receive activity {1} - message validation failed. Message will be discarded.",
                            this.WorkflowInstanceId, this.QualifiedName);
 
                        requestContext.SendFault(new FaultException(SR2.GetString(SR2.SecurityCheckFailed)), null);
                    }
                    catch (CommunicationException cex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, cex);
                    }
                    catch (TimeoutException tex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, tex);
                    }
 
                    if (requestContext.ContextProperties == null ||
                        !(requestContext.ContextProperties.Keys.Contains(WellKnownContextProperties.InstanceId)))
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new FaultException(SR2.GetString(SR2.Error_FailedToValidateActivatingMessage, this.WorkflowInstanceId)));
                    }
                }
            }
        }
 
        void IEventActivity.Subscribe(ActivityExecutionContext parentContext,
            IActivityEventListener<QueueEventArgs> parentEventHandler)
        {
            if (parentContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentContext");
            }
 
            if (parentEventHandler == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentEventHandler");
            }
 
            if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
            {
                this.QueueInitializationMode = QueueInitializationMode.EventDriven;
            }
 
            // make sure that we are getting the proper queue
            // even if that means creating a new queue
            // given our conversation context and execution context.
            //
            WorkflowQueue workflowQueue = GetWorkflowQueue(parentContext);
            if (workflowQueue != null)
            {
                if (this.QueueInitializationMode == QueueInitializationMode.EventDriven)
                {
                    workflowQueue.Enabled = true;
                }
 
                if (this.validationShim == null)
                {
                    this.validationShim = new ValidationShim(this, parentEventHandler);
                }
                if (this.securityShim == null)
                {
                    this.securityShim = new SecurityShim(this);
                }
 
                workflowQueue.RegisterForQueueItemArrived(this.securityShim);
                workflowQueue.RegisterForQueueItemAvailable(this.validationShim, this.QualifiedName);
            }
 
            return;
        }
 
        void IEventActivity.Unsubscribe(ActivityExecutionContext parentContext,
            IActivityEventListener<QueueEventArgs> parentEventHandler)
        {
            if (parentContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentContext");
            }
 
            if (parentEventHandler == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentEventHandler");
            }
 
            WorkflowQueuingService queuingService = parentContext.GetService<WorkflowQueuingService>();
            if (queuingService == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
                    typeof(WorkflowQueuingService))));
            }
 
            // get the queue using the queue name
            // at this point the conversation context should have been re-initialized if necessary
            //            
            WorkflowQueue workflowQueue = queuingService.GetWorkflowQueue(((IEventActivity)this).QueueName);
            if (workflowQueue == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
                    ((IEventActivity)this).QueueName)));
            }
 
            if (this.securityShim != null)
            {
                workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
                this.securityShim = null;
            }
            if (this.validationShim != null)
            {
                workflowQueue.UnregisterForQueueItemAvailable(this.validationShim);
            }
 
            if (this.QueueInitializationMode == QueueInitializationMode.EventDriven)
            {
                workflowQueue.Enabled = false;
            }
 
            return;
        }
 
        [SuppressMessage("Microsoft.Security", "CA2103")] // Review imperative security, because constructing PrincipalPermission
        void IServiceDescriptionBuilder.BuildServiceDescription(ServiceDescriptionContext context)
        {
            if (context == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
            }
 
            if (!this.Enabled)
            {
                return;
            }
 
            OperationInfoBase serviceOperationInfo = this.ServiceOperationInfo;
            if (serviceOperationInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, this.Name)));
            }
 
            // set the workflow service behavior
            //
            IServiceDescriptionBuilder serviceAttributes =
                GetWorkflowServiceAttributes(this.RootActivity) as IServiceDescriptionBuilder;
 
            if (serviceAttributes != null)
            {
                serviceAttributes.BuildServiceDescription(context);
            }
 
            if (context.ReflectedContracts == null || context.WorkflowOperationBehaviors == null)
            {
                return;
            }
 
            // add contract types and configure the operation behavior
            //
            Type contractType = serviceOperationInfo.GetContractType(((IComponent)this).Site);
 
            List<Type> interfaces = ServiceOperationHelpers.GetContracts(contractType);
            for (int i = 0; i < interfaces.Count; i++)
            {
                Type interfaceType = interfaces[i];
                ContractDescription contractDescription = null;
 
                if (!context.ReflectedContracts.Contains(interfaceType))
                {
                    contractDescription = ContractDescription.GetContract(interfaceType);
                    ServiceOperationHelpers.SetWorkflowOperationBehavior(contractDescription, context);
 
                    context.Contracts.Add(contractDescription.ConfigurationName, contractDescription);
                    context.ReflectedContracts.Add(contractDescription.ContractType);
                }
                else
                {
                    contractDescription = context.Contracts[ContractDescription.GetContract(interfaceType).ConfigurationName];
                }
 
                Collection<ContractDescription> inheritedContractDescriptions = contractDescription.GetInheritedContracts();
                for (int j = 0; j < inheritedContractDescriptions.Count; j++)
                {
                    ContractDescription inheritedContractDescription = inheritedContractDescriptions[j];
                    if (!context.ReflectedContracts.Contains(inheritedContractDescription.ContractType))
                    {
                        ServiceOperationHelpers.SetWorkflowOperationBehavior(inheritedContractDescription, context);
 
                        context.Contracts.Add(inheritedContractDescription.ConfigurationName, inheritedContractDescription);
                        context.ReflectedContracts.Add(inheritedContractDescription.ContractType);
                    }
                }
            }
 
            Type operationDeclaringType = null;
            MethodInfo methodInfo = serviceOperationInfo.GetMethodInfo(((IComponent)this).Site);
            if (methodInfo != null)
            {
                operationDeclaringType = methodInfo.DeclaringType;
            }
 
            if (operationDeclaringType != null)
            {
                WorkflowOperationBehavior behavior = null;
                KeyValuePair<Type, string> operationKey =
                    new KeyValuePair<Type, string>(operationDeclaringType, serviceOperationInfo.Name);
 
                if (context.WorkflowOperationBehaviors.TryGetValue(operationKey, out behavior) && behavior != null)
                {
                    if (!behavior.CanCreateInstance && this.CanCreateInstance)
                    {
                        behavior.CanCreateInstance = true;
                    }
 
                    if (!string.IsNullOrEmpty(serviceOperationInfo.PrincipalPermissionRole)
                        || !string.IsNullOrEmpty(serviceOperationInfo.PrincipalPermissionName))
                    {
                        if (behavior.ServiceAuthorizationManager == null)
                        {
                            PrincipalPermission permission =
                                new PrincipalPermission(serviceOperationInfo.PrincipalPermissionName,
                                serviceOperationInfo.PrincipalPermissionRole, true);
 
                            PrincipalPermissionServiceAuthorizationManager authManager
                                = new PrincipalPermissionServiceAuthorizationManager(permission);
 
                            behavior.ServiceAuthorizationManager = authManager;
                        }
                    }
                }
            }
        }
 
        protected internal override void Initialize(IServiceProvider provider)
        {
            if (provider == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("provider");
            }
 
            ContextToken.Register(this, this.WorkflowInstanceId);
 
            SetQueueInitializationMode();
 
            // make sure that we are getting the proper queue
            // even if that means creating a new queue
            // given our conversation context and execution context.
            //
            WorkflowQueue workflowQueue = GetWorkflowQueue(provider);
            if (workflowQueue == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
                    ((IEventActivity)this).QueueName)));
            }
 
            if (this.QueueInitializationMode == QueueInitializationMode.StateMachine)
            {
                workflowQueue.Enabled = true;
            }
 
            base.Initialize(provider);
        }
 
        internal void GetParameterPropertyDescriptors(IDictionary properties)
        {
            if (properties == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("properties");
            }
 
            if (((IComponent)this).Site == null)
            {
                return;
            }
 
            OperationInfoBase serviceOperationInfo = this.ServiceOperationInfo;
            if (serviceOperationInfo != null)
            {
                MethodInfo methodInfo = serviceOperationInfo.GetMethodInfo(((IComponent)this).Site);
                if (methodInfo != null)
                {
                    ArrayList paramInfo = new ArrayList(methodInfo.GetParameters());
                    if (!(methodInfo.ReturnType == typeof(void)))
                    {
                        paramInfo.Add(methodInfo.ReturnParameter);
                    }
 
                    foreach (ParameterInfo param in paramInfo)
                    {
                        if (param.ParameterType != null)
                        {
                            PropertyDescriptor prop =
                                new ParameterInfoBasedPropertyDescriptor(typeof(ReceiveActivity),
                                param, true, DesignOnlyAttribute.Yes);
 
                            properties[prop.Name] = prop;
                        }
                    }
                }
            }
        }
 
        protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext)
        {
            try
            {
                if (executionContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
                }
 
                WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
                if (queuingService == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
                        typeof(WorkflowQueuingService))));
                }
 
                WorkflowQueue workflowQueue = GetWorkflowQueue(executionContext);
                if (workflowQueue == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
                        ((IEventActivity)this).QueueName)));
                }
 
                workflowQueue.UnregisterForQueueItemAvailable(this);
 
                if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
                {
                    if (this.securityShim != null)
                    {
                        workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
                        this.securityShim = null;
                    }
                    workflowQueue.Enabled = false;
                }
            }
            finally
            {
                RemoveRequestContext();
            }
 
            return base.Cancel(executionContext);
        }
 
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (executionContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
            }
 
            WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
            if (queuingService == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
                    typeof(WorkflowQueuingService))));
            }
 
            // make sure that we are getting the proper queue
            // even if that means creating a new queue
            // given our conversation context and execution context.
            //
            WorkflowQueue workflowQueue = GetWorkflowQueue(executionContext);
            if (workflowQueue == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
                    ((IEventActivity)this).QueueName)));
            }
 
            if (this.QueueInitializationMode == QueueInitializationMode.Standalone && workflowQueue.Count == 0)
            {
                workflowQueue.Enabled = true;
 
                if (this.securityShim == null)
                {
                    this.securityShim = new SecurityShim(this);
                }
                workflowQueue.RegisterForQueueItemArrived(this.securityShim);
                workflowQueue.RegisterForQueueItemAvailable(this, this.QualifiedName);
                return ActivityExecutionStatus.Executing;
            }
            else if (workflowQueue.Count == 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
                    this.QualifiedName)));
            }
 
            WorkflowRequestContext requestContext = workflowQueue.Dequeue() as WorkflowRequestContext;
 
            if (requestContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
                    this.QualifiedName)));
            }
            else
            {
                if (this.validationShim != null)
                {
                    this.RequestContext = requestContext;
                    CacheRequestContext(requestContext);
                }
                else if (ValidationShim.EvaluateSecurityConstraints(executionContext, this, requestContext) == true)
                {
                    this.RequestContext = requestContext;
                    CacheRequestContext(requestContext);
 
                    if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
                    {
                        workflowQueue.Enabled = false;
                    }
                }
                else
                {
                    try
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                            "Workflow Instance {0}, receive activity {1} - message validation failed. Message will be discarded.",
                            this.WorkflowInstanceId, this.QualifiedName);
 
                        requestContext.SendFault(new FaultException(SR2.GetString(SR2.SecurityCheckFailed)), null);
                    }
                    catch (CommunicationException cex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, cex);
                    }
                    catch (TimeoutException tex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, tex);
                    }
 
                    if (requestContext.ContextProperties == null ||
                        !(requestContext.ContextProperties.Keys.Contains(WellKnownContextProperties.InstanceId)))
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new FaultException(SR2.GetString(SR2.Error_FailedToValidateActivatingMessage, this.WorkflowInstanceId)));
                    }
 
                    if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
                    {
                        if (this.securityShim == null)
                        {
                            this.securityShim = new SecurityShim(this);
                        }
                        workflowQueue.RegisterForQueueItemArrived(this.securityShim);
                    }
 
                    workflowQueue.RegisterForQueueItemAvailable(this, this.QualifiedName);
                    return ActivityExecutionStatus.Executing;
                }
            }
 
            return ExecuteActivity(this.RequestContext, executionContext);
        }
 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
            Justification = "Supress any exceptions thrown by SendFault to avoid calling HandleFault infinitely.")]
        protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext,
            Exception exception)
        {
            try
            {
                if (executionContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
                }
 
                if (exception == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("exception");
                }
 
                if (executionContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
                }
 
                WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
                if (queuingService == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
                        typeof(WorkflowQueuingService))));
                }
 
                WorkflowQueue workflowQueue = GetWorkflowQueue(executionContext);
                if (workflowQueue == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
                        ((IEventActivity)this).QueueName)));
                }
 
                workflowQueue.UnregisterForQueueItemAvailable(this);
 
                if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
                {
                    if (this.securityShim != null)
                    {
                        workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
                        this.securityShim = null;
                    }
                    workflowQueue.Enabled = false;
                }
 
                RestoreRequestContext();
 
                if (this.RequestContext != null)
                {
                    System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                         "Workflow Instance {0}, receive activity {1} - sending fault response message",
                         this.WorkflowInstanceId, this.QualifiedName);
 
                    if (this.FaultMessage != null)
                    {
                        try
                        {
                            this.RequestContext.SendFault(this.FaultMessage, null);
                        }
                        catch
                        {
                            System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                                "Workflow Instance {0}, receive activity {1} - failed to send response fault message.",
                                this.WorkflowInstanceId, this.QualifiedName);
                        }
                    }
                    else
                    {
                        try
                        {
                            this.RequestContext.SendFault(exception, null);
                        }
                        catch
                        {
                            System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                                "Workflow Instance {0}, receive activity {1} - failed to send response fault message.",
                                this.WorkflowInstanceId, this.QualifiedName);
                        }
                    }
                }
            }
            finally
            {
                RemoveRequestContext();
            }
 
            return base.HandleFault(executionContext, exception);
        }
 
        protected override void InitializeProperties()
        {
            OperationInfoBase serviceOperationInfo = this.ServiceOperationInfo;
 
            if (serviceOperationInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, this.Name)));
            }
 
            OperationParameterInfoCollection parameters = null;
 
            Activity definitionRoot = base.RootActivity.GetValue(Activity.WorkflowDefinitionProperty) as Activity;
            if (definitionRoot != null)
            {
                ReceiveActivity definition = definitionRoot.GetActivityByName(this.QualifiedName, true) as ReceiveActivity;
                if ((definition != null) && definition.UserData.Contains(typeof(OperationParameterInfoCollection)))
                {
                    parameters = definition.UserData[typeof(OperationParameterInfoCollection)] as OperationParameterInfoCollection;
                }
            }
 
            if (parameters == null)
            {
                parameters = serviceOperationInfo.GetParameters(this.Site);
                this.UserData[typeof(OperationParameterInfoCollection)] = parameters;
            }
 
            WorkflowParameterBindingCollection bindings = this.ParameterBindings;
 
            foreach (OperationParameterInfo parameter in parameters)
            {
                if (!bindings.Contains(parameter.Name))
                {
                    bindings.Add(new WorkflowParameterBinding(parameter.Name));
                }
            }
 
            base.InitializeProperties();
        }
 
        protected override void OnSequenceComplete(ActivityExecutionContext executionContext)
        {
            if (executionContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
            }
 
            try
            {
                RestoreRequestContext();
                if (this.RequestContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
                        this.QualifiedName)));
                }
 
                object returnValue;
                object[] outputValues;
 
                if (this.FaultMessage != null)
                {
                    System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                        "Workflow Instance {0}, receive activity {1} - sending fault response message",
                        this.WorkflowInstanceId, this.QualifiedName);
 
                    try
                    {
                        this.RequestContext.SendFault(this.FaultMessage, null);
                    }
                    catch (CommunicationException cex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send fault response message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, cex);
                        throw;
                    }
                    catch (TimeoutException tex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send fault response message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, tex);
                        throw;
                    }
                }
                else if (!this.OperationHelper.IsOneWay)
                {
                    returnValue = this.OperationHelper.GetOutputs(this, out outputValues);
 
                    System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                        "Workflow Instance {0}, receive activity {1} - sending response message",
                        this.WorkflowInstanceId, this.QualifiedName);
 
                    try
                    {
                        this.RequestContext.SendReply(returnValue, outputValues, null);
                    }
                    catch (CommunicationException cex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send response message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, cex);
                        throw;
                    }
                    catch (TimeoutException tex)
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                            "Workflow Instance {0}, receive activity {1} - failed to send response message. Error: {2}",
                            this.WorkflowInstanceId, this.QualifiedName, tex);
                        throw;
                    }
                }
                else
                {
                    System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                        "Workflow Instance {0}, receive activity {1} - completing one way operation",
                        this.WorkflowInstanceId, this.QualifiedName);
 
                    this.RequestContext.SetOperationCompleted();
                }
 
                base.OnSequenceComplete(executionContext);
 
                // Null out the request context to reduce serialization size of the activity.
                this.RequestContext = null;
            }
            finally
            {
                RemoveRequestContext();
            }
        }
 
        static object GetWorkflowServiceAttributesValueOverride(object dependencyObject)
        {
            if (dependencyObject == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dependencyObject");
            }
 
            if (!(dependencyObject is Activity))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                    "dependencyObject",
                    SR2.GetString(SR2.Error_UnexpectedArgumentType, typeof(Activity).FullName));
            }
 
            Activity activity = dependencyObject as Activity;
 
            if (activity.GetValueBase(ReceiveActivity.WorkflowServiceAttributesProperty) == null)
            {
                if (activity.DesignMode)
                {
                    WorkflowServiceAttributes workflowServiceAttribsValue = new WorkflowServiceAttributes();
                    Activity rootActivity = activity.RootActivity;
                    if (rootActivity != null)
                    {
                        string fullClassName = (String)rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty);
                        if (!String.IsNullOrEmpty(fullClassName))
                        {
                            string namespaceName;
                            string className;
                            Helpers.GetNamespaceAndClassName(fullClassName, out namespaceName, out className);
                            workflowServiceAttribsValue.ConfigurationName = fullClassName;
                            workflowServiceAttribsValue.Name = className;
                        }
                    }
                    activity.SetValue(ReceiveActivity.WorkflowServiceAttributesProperty, workflowServiceAttribsValue);
                    return workflowServiceAttribsValue;
                }
            }
            return activity.GetValueBase(ReceiveActivity.WorkflowServiceAttributesProperty);
        }
 
        private ActivityExecutionStatus ExecuteActivity(WorkflowRequestContext requestContext,
            ActivityExecutionContext executionContext)
        {
            if (requestContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requestContext");
            }
 
            if (executionContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
            }
 
            System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                "Workflow Instance {0}, receive activity {1} - received message",
                this.WorkflowInstanceId, this.QualifiedName);
 
            this.OperationHelper.PopulateInputs(this, requestContext.Inputs);
 
            return base.Execute(executionContext);
        }
 
        private WorkflowQueue GetWorkflowQueue(IServiceProvider provider)
        {
            if (provider == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("provider");
            }
 
            if (this.ServiceOperationInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, this.Name)));
            }
 
            WorkflowQueuingService queuingService =
                provider.GetService(typeof(WorkflowQueuingService)) as WorkflowQueuingService;
 
            if (queuingService == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
                    typeof(WorkflowQueuingService))));
            }
 
            WorkflowQueue workflowQueue = null;
            string queueName = this.OperationHelper.GetWorkflowQueueName(this.Context);
            this.SetValue(QueueNameProperty, queueName);
 
            if (!queuingService.Exists(queueName))
            {
                workflowQueue = queuingService.CreateWorkflowQueue(queueName, false);
                workflowQueue.Enabled = false;
            }
            else
            {
                workflowQueue = queuingService.GetWorkflowQueue(queueName);
            }
 
            return workflowQueue;
        }
 
        private void SetQueueInitializationMode()
        {
            if (this.parent != null && this.parent is EventDrivenActivity)
            {
                if (this.parent.parent != null && this.parent.parent is StateActivity)
                {
                    this.QueueInitializationMode = QueueInitializationMode.StateMachine;
                }
            }
        }
 
        private void CacheRequestContext(WorkflowRequestContext requestContext)
        {
            string keyValue = WorkflowEnvironment.WorkflowInstanceId.ToString() + ":" +
                this.GetValue(ReceiveActivity.QueueNameProperty) as string;
            requestContextsCache[keyValue] = requestContext;
            this.isContextCached = true;
        }
 
        private void RestoreRequestContext()
        {
            string keyValue = WorkflowEnvironment.WorkflowInstanceId.ToString() + ":"
                + this.GetValue(ReceiveActivity.QueueNameProperty) as string;
            if (requestContextsCache.ContainsKey(keyValue))
            {
                this.RequestContext = requestContextsCache[keyValue] as WorkflowRequestContext;
            }
        }
 
        private void RemoveRequestContext()
        {
            requestContextsCache.Remove(WorkflowEnvironment.WorkflowInstanceId.ToString() + ":" +
                this.GetValue(ReceiveActivity.QueueNameProperty) as string);
        }
 
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (disposing && this.isContextCached)
                {
                    RemoveRequestContext();
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }
 
        [Serializable]
        class ReceiveOperationInfoHelper
        {
            string baseQueueName;
            bool hasReturnValue = false;
            IList<KeyValuePair<int, string>> inputParameters;
            bool isOneWay = false;
            IDictionary<int, Type> notNullableParameters;
            bool nullableReturnValue = true;
            string operationName;
            IList<KeyValuePair<int, string>> outputParameters;
            string returnTypeName;
 
            public ReceiveOperationInfoHelper(IServiceProvider serviceProvider, ReceiveActivity activity)
            {
                outputParameters = new List<KeyValuePair<int, string>>();
                inputParameters = new List<KeyValuePair<int, string>>();
                notNullableParameters = new Dictionary<int, Type>();
                hasReturnValue = false;
                nullableReturnValue = true;
 
                if (activity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
                }
 
                OperationInfoBase serviceOperationInfo = activity.ServiceOperationInfo;
                if (serviceOperationInfo == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, activity.Name)));
                }
 
                MethodInfo methodInfo = serviceOperationInfo.GetMethodInfo(serviceProvider);
                if (methodInfo == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.Error_MethodInfoNotAvailable, activity.Name)));
                }
 
                if (methodInfo.ReturnType != null && methodInfo.ReturnType != typeof(void))
                {
                    hasReturnValue = true;
                    this.returnTypeName = methodInfo.ReturnType.FullName;
                    nullableReturnValue =
                        !((methodInfo.ReturnType.IsPrimitive || methodInfo.ReturnType.IsEnum || methodInfo.ReturnType.IsValueType) && !ServiceOperationHelpers.IsNullableType(methodInfo.ReturnType));
                }
 
                foreach (ParameterInfo parameter in methodInfo.GetParameters())
                {
                    if (parameter.ParameterType.IsByRef ||
                        parameter.IsOut || (parameter.IsIn && parameter.IsOut))
                    {
                        outputParameters.Add(new KeyValuePair<int, string>(parameter.Position, parameter.Name));
 
                        if (parameter.ParameterType.IsByRef &&
                            parameter.ParameterType.GetElementType().IsValueType &&
                            !ServiceOperationHelpers.IsNullableType(parameter.ParameterType))
                        {
                            notNullableParameters.Add(parameter.Position, parameter.ParameterType);
                        }
                    }
 
                    if (!parameter.IsOut || (parameter.IsIn && parameter.IsOut))
                    {
                        inputParameters.Add(new KeyValuePair<int, string>(parameter.Position, parameter.Name));
                    }
                }
 
                this.operationName = serviceOperationInfo.Name;
 
                this.baseQueueName = QueueNameHelper.Create(methodInfo.DeclaringType, this.operationName);
 
                object[] operationContractAttribs = methodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true);
 
                if (operationContractAttribs != null && operationContractAttribs.Length > 0)
                {
                    if (operationContractAttribs[0] is OperationContractAttribute)
                    {
                        this.isOneWay = ((OperationContractAttribute)operationContractAttribs[0]).IsOneWay;
                    }
                }
 
            }
 
            public bool IsOneWay
            {
                get
                {
                    return this.isOneWay;
                }
            }
 
            public object GetOutputs(ReceiveActivity activity, out object[] outputs)
            {
                if (activity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
                }
 
                outputs = new object[outputParameters.Count];
                object returnValue = null;
 
                WorkflowParameterBindingCollection bindings = activity.ParameterBindings;
 
                for (int index = 0; index < outputParameters.Count; ++index)
                {
                    KeyValuePair<int, string> parameterInfo = outputParameters[index];
                    if (bindings[parameterInfo.Value].Value == null &&
                        this.notNullableParameters.Keys.Contains(parameterInfo.Key))
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new InvalidOperationException(SR2.GetString(SR2.Error_ReceiveActivityInvalidParameterValue,
                            activity.Name, parameterInfo.Value, this.notNullableParameters[parameterInfo.Key])));
                    }
 
                    outputs[index] = bindings[parameterInfo.Value].Value;
                }
 
                if (hasReturnValue)
                {
                    if (bindings["(ReturnValue)"].Value == null &&
                        !this.nullableReturnValue)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new InvalidOperationException(SR2.GetString(SR2.Error_ReceiveActivityInvalidReturnValue,
                            activity.Name, this.returnTypeName)));
                    }
 
                    returnValue = bindings["(ReturnValue)"].Value;
                }
 
                return returnValue;
            }
 
            public string GetWorkflowQueueName(IDictionary<string, string> context)
            {
                return QueueNameHelper.Create(this.baseQueueName, context);
            }
 
            public void PopulateInputs(ReceiveActivity activity, ReadOnlyCollection<object> inputs)
            {
                if (activity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
                }
 
                if (inputs == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("inputs");
                }
 
                WorkflowParameterBindingCollection bindings = activity.ParameterBindings;
 
                for (int index = 0; index < inputParameters.Count; index++)
                {
                    KeyValuePair<int, string> parameterInfo = inputParameters[index];
 
                    if (!bindings.Contains(parameterInfo.Value))
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new InvalidOperationException(SR2.GetString(SR2.Error_ParameterBindingMissing,
                            parameterInfo.Value,
                            this.operationName,
                            activity.Name)));
                    }
                    if (index >= inputs.Count)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new InvalidOperationException(SR2.GetString(SR2.Error_InputValueUnavailable,
                            parameterInfo.Value,
                            this.operationName,
                            activity.Name)));
                    }
 
                    WorkflowParameterBinding parameterBinding = bindings[parameterInfo.Value];
                    parameterBinding.Value = inputs[index];
                }
            }
        }
 
        [Serializable]
        class SecurityShim : IActivityEventListener<QueueEventArgs>, IDisposable
        {
            ReceiveActivity receiveActivity;
 
            internal SecurityShim(ReceiveActivity receiveActivity)
            {
                if (receiveActivity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("receiveActivity");
                }
 
                this.receiveActivity = receiveActivity;
            }
 
            void IActivityEventListener<QueueEventArgs>.OnEvent(object sender, QueueEventArgs queueEventArgs)
            {
                if (sender == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sender");
                }
 
                if (queueEventArgs == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("queueEventArgs");
                }
 
                WorkflowQueue workflowQueue = sender as WorkflowQueue;
                if (workflowQueue == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new ArgumentException(SR2.GetString(SR2.Error_ArgumentTypeInvalid, "sender", typeof(WorkflowQueue))));
                }
 
                WorkflowRequestContext requestContext = workflowQueue.Peek() as WorkflowRequestContext;
                if (requestContext != null)
                {
                    IDependencyObjectAccessor doa = (IDependencyObjectAccessor)receiveActivity;
                    EventHandler<OperationValidationEventArgs>[] eventHandlers =
                        doa.GetInvocationList<EventHandler<OperationValidationEventArgs>>(
                        ReceiveActivity.OperationValidationEvent);
 
                    if (eventHandlers != null && eventHandlers.Length > 0)
                    {
                        requestContext.PopulateAuthorizationState();
                    }
                }
            }
 
            void IDisposable.Dispose()
            {
                this.receiveActivity.Dispose();
                GC.SuppressFinalize(this);
            }
        }
 
        [Serializable]
        class ValidationShim : IActivityEventListener<QueueEventArgs>, IDisposable
        {
            IActivityEventListener<QueueEventArgs> activityEventListener;
            ReceiveActivity receiveActivity;
 
            internal ValidationShim(ReceiveActivity receiveActivity, IActivityEventListener<QueueEventArgs> activityEventListener)
            {
                if (receiveActivity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("receiveActivity");
                }
 
                if (activityEventListener == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activityEventListener");
                }
 
                this.receiveActivity = receiveActivity;
                this.activityEventListener = activityEventListener;
            }
 
            void IActivityEventListener<QueueEventArgs>.OnEvent(object sender, QueueEventArgs queueEventArgs)
            {
                if (sender == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sender");
                }
 
                if (queueEventArgs == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("queueEventArgs");
                }
 
                ActivityExecutionContext executionContext = sender as ActivityExecutionContext;
                if (executionContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new ArgumentException(SR2.GetString(SR2.Error_ArgumentTypeInvalid, "sender", typeof(ActivityExecutionContext))));
                }
 
                WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
                if (queuingService == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.General_MissingService, typeof(WorkflowQueuingService))));
                }
 
                WorkflowQueue workflowQueue = queuingService.GetWorkflowQueue(queueEventArgs.QueueName);
                if (workflowQueue == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound, queueEventArgs.QueueName)));
                }
 
                WorkflowRequestContext requestContext = workflowQueue.Peek() as WorkflowRequestContext;
                if (requestContext != null)
                {
                    if (EvaluateSecurityConstraints(executionContext, this.receiveActivity, requestContext) == true)
                    {
                        this.activityEventListener.OnEvent(sender, queueEventArgs);
                    }
                    else
                    {
                        System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
                            "Workflow Instance {0}, receive activity {1} - message validation failed. Message will be discarded.",
                            this.receiveActivity.WorkflowInstanceId, this.receiveActivity.QualifiedName);
 
                        workflowQueue.Dequeue();
                        try
                        {
                            requestContext.SendFault(new FaultException(SR2.GetString(SR2.SecurityCheckFailed)), null);
                        }
                        catch (CommunicationException cex)
                        {
                            System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                                "Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
                                this.receiveActivity.WorkflowInstanceId, this.receiveActivity.QualifiedName, cex);
                        }
                        catch (TimeoutException tex)
                        {
                            System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
                                "Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
                                this.receiveActivity.WorkflowInstanceId, this.receiveActivity.QualifiedName, tex);
                        }
 
                        if (requestContext.ContextProperties == null ||
                            !(requestContext.ContextProperties.Keys.Contains(WellKnownContextProperties.InstanceId)))
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new FaultException(SR2.GetString(SR2.Error_FailedToValidateActivatingMessage, this.receiveActivity.WorkflowInstanceId)));
                        }
                    }
                }
                else
                {
                    this.activityEventListener.OnEvent(sender, queueEventArgs);
                }
            }
 
            void IDisposable.Dispose()
            {
                this.receiveActivity.Dispose();
                GC.SuppressFinalize(this);
            }
 
            internal static bool EvaluateSecurityConstraints(IServiceProvider serviceProvider, ReceiveActivity receiveActivity, WorkflowRequestContext requestContext)
            {
                bool retVal = true;
 
                if (serviceProvider == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceProvider");
                }
 
                if (receiveActivity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("receiveActivity");
                }
 
                if (requestContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requestContext");
                }
 
                IDependencyObjectAccessor doa = (IDependencyObjectAccessor)receiveActivity;
                EventHandler<OperationValidationEventArgs>[] eventHandlers =
                    doa.GetInvocationList<EventHandler<OperationValidationEventArgs>>(
                    ReceiveActivity.OperationValidationEvent);
 
                if (eventHandlers != null && eventHandlers.Length > 0)
                {
                    ReadOnlyCollection<ClaimSet> claims = requestContext.AuthorizationContext == null ?
                        new ReadOnlyCollection<ClaimSet>(new List<ClaimSet>()) :
                        requestContext.AuthorizationContext.ClaimSets;
                    OperationValidationEventArgs e = new OperationValidationEventArgs(claims);
                    receiveActivity.RaiseGenericEvent(ReceiveActivity.OperationValidationEvent,
                        receiveActivity, e);
                    retVal = e.IsValid;
                }
 
                return retVal;
            }
        }
    }
}