opensim-development – Rev 1

Subversion Repositories:
Rev:

#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)

using System;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.Web;
using System.Runtime.Remoting.Messaging;


namespace Amib.Threading.Internal
{
#region CallerThreadContext class

        /// <summary>
        /// This class stores the caller call context in order to restore
        /// it when the work item is executed in the thread pool environment. 
        /// </summary>
        internal class CallerThreadContext 
        {
#region Prepare reflection information

                // Cached type information.
                private static readonly MethodInfo getLogicalCallContextMethodInfo =
                        typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);

                private static readonly MethodInfo setLogicalCallContextMethodInfo =
                        typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);

                private static string HttpContextSlotName = GetHttpContextSlotName();

                private static string GetHttpContextSlotName()
                {
                        FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);

            if (fi != null)
            {
                return (string) fi.GetValue(null);
            }

                    return "HttpContext";
                }

        #endregion

#region Private fields

                private HttpContext _httpContext;
                private LogicalCallContext _callContext;

        #endregion

                /// <summary>
                /// Constructor
                /// </summary>
                private CallerThreadContext()
                {
                }

                public bool CapturedCallContext
                {
                        get
                        {
                                return (null != _callContext);
                        }
                }

                public bool CapturedHttpContext
                {
                        get
                        {
                                return (null != _httpContext);
                        }
                }

                /// <summary>
                /// Captures the current thread context
                /// </summary>
                /// <returns></returns>
                public static CallerThreadContext Capture(
                        bool captureCallContext, 
                        bool captureHttpContext)
                {
                        Debug.Assert(captureCallContext || captureHttpContext);

                        CallerThreadContext callerThreadContext = new CallerThreadContext();

                        // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
                        // Capture Call Context
                        if(captureCallContext && (getLogicalCallContextMethodInfo != null))
                        {
                                callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
                                if (callerThreadContext._callContext != null)
                                {
                                        callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
                                }
                        }

                        // Capture httpContext
                        if (captureHttpContext && (null != HttpContext.Current))
                        {
                                callerThreadContext._httpContext = HttpContext.Current;
                        }

                        return callerThreadContext;
                }

                /// <summary>
                /// Applies the thread context stored earlier
                /// </summary>
                /// <param name="callerThreadContext"></param>
                public static void Apply(CallerThreadContext callerThreadContext)
                {
                        if (null == callerThreadContext) 
                        {
                                throw new ArgumentNullException("callerThreadContext");                 
                        }

                        // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
                        // Restore call context
                        if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
                        {
                                setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
                        }

                        // Restore HttpContext 
                        if (callerThreadContext._httpContext != null)
                        {
                HttpContext.Current = callerThreadContext._httpContext;
                                //CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
                        }
                }
        }

    #endregion
}
#endif