File: System\Web\Services\Protocols\WebServiceHandlerFactory.cs
Project: ndp\cdf\src\NetFx20\System.Web.Services\System.Web.Services.csproj (System.Web.Services)
//------------------------------------------------------------------------------
// <copyright file="WebServiceHandlerFactory.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
namespace System.Web.Services.Protocols {
 
    using System.Diagnostics;
    using System;
    using Microsoft.Win32;
    //using System.Reflection;
    using System.Web.UI;
    using System.ComponentModel; // for CompModSwitches
    using System.IO;
    using System.Web.Services.Configuration;
    using System.Security.Permissions;
    using System.Threading;
    using System.Web.Services.Diagnostics;
 
    /// <include file='doc\WebServiceHandlerFactory.uex' path='docs/doc[@for="WebServiceHandlerFactory"]/*' />
    /// <devdoc>
    ///    <para>[To be supplied.]</para>
    /// </devdoc>
    [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
    public class WebServiceHandlerFactory : IHttpHandlerFactory {
        /*
        static WebServiceHandlerFactory() {            
            Stream stream = new FileStream("c:\\out.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); //(FileMode.OpenOrCreate);            
            TraceListener listener = new TextWriterTraceListener(stream);            
            Debug.AutoFlush = true;            
            Debug.Listeners.Add(listener);            
            Debug.WriteLine("--------------");            
        }
        */
 
#if DEBUG
        void DumpRequest(HttpContext context) {
            HttpRequest request = context.Request;
            Debug.WriteLine("Process Request called.");
            Debug.WriteLine("Path = " + request.Path);
            Debug.WriteLine("PhysicalPath = " + request.PhysicalPath);
            Debug.WriteLine("Query = " + request.Url.Query);
            Debug.WriteLine("HttpMethod = " + request.HttpMethod);
            Debug.WriteLine("ContentType = " + request.ContentType);
            Debug.WriteLine("PathInfo = " + request.PathInfo);
            Debug.WriteLine("----Http request headers: ----");
            System.Collections.Specialized.NameValueCollection headers = request.Headers;
            foreach (string name in headers) {
                string value = headers[name];
                if (value != null && value.Length > 0)
                    Debug.WriteLine(name + "=" + headers[name]);
            }                
        }
#endif
 
 
        /// <include file='doc\WebServiceHandlerFactory.uex' path='docs/doc[@for="WebServiceHandlerFactory.GetHandler"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public IHttpHandler GetHandler(HttpContext context, string verb, string url, string filePath) {
            TraceMethod method = Tracing.On ? new TraceMethod(this, "GetHandler") : null;
            if (Tracing.On) Tracing.Enter("IHttpHandlerFactory.GetHandler", method, Tracing.Details(context.Request));
 
            new AspNetHostingPermission(AspNetHostingPermissionLevel.Minimal).Demand();
            //if (CompModSwitches.Remote.TraceVerbose) DumpRequest(context);
            //System.Diagnostics.Debugger.Break();
#if DEBUG
            if (CompModSwitches.Remote.TraceVerbose) DumpRequest(context);
#endif
 
            Type type = GetCompiledType(url, context);
            IHttpHandler handler = CoreGetHandler(type, context, context.Request, context.Response);
 
            if (Tracing.On) Tracing.Exit("IHttpHandlerFactory.GetHandler", method);
 
            return handler;
        }
 
        // Asserts security permission. 
        // Reason: System.Web.UI.WebServiceParser.GetCompiledType() demands SecurityPermission.
        // Justification: The type returned is only used to get the IHttpHandler.
        [SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
        private Type GetCompiledType(string url, HttpContext context)
        {
            return WebServiceParser.GetCompiledType(url, context);
        }
 
        internal IHttpHandler CoreGetHandler(Type type, HttpContext context, HttpRequest request, HttpResponse response) {
            TraceMethod caller = Tracing.On ? new TraceMethod(this, "CoreGetHandler") : null;
            ServerProtocolFactory[] protocolFactories = GetServerProtocolFactories();
            ServerProtocol protocol = null;
            bool abort = false;
            for (int i = 0; i < protocolFactories.Length; i++) {
                try {
                    protocol = protocolFactories[i].Create(type, context, request, response, out abort);
                    if ((protocol != null && protocol.GetType() != typeof(UnsupportedRequestProtocol)) || abort)
                        break;
                }
                catch (Exception e) {
                    if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
                        throw;
                    }
                    throw Tracing.ExceptionThrow(caller, new InvalidOperationException(Res.GetString(Res.FailedToHandleRequest0), e));
                }
            }
 
            if (abort)
                return new NopHandler();
 
            if (protocol == null) {
                if (request.PathInfo != null && request.PathInfo.Length != 0) {
                    throw Tracing.ExceptionThrow(caller, new InvalidOperationException(Res.GetString(Res.WebUnrecognizedRequestFormatUrl,
                        new object[] { request.PathInfo })));
                }
                else {
                    throw Tracing.ExceptionThrow(caller, new InvalidOperationException(Res.GetString(Res.WebUnrecognizedRequestFormat)));
                }
            }
            else if (protocol is UnsupportedRequestProtocol) {
                throw Tracing.ExceptionThrow(caller, new HttpException(((UnsupportedRequestProtocol)protocol).HttpCode, Res.GetString(Res.WebUnrecognizedRequestFormat)));
            }
 
            bool isAsync = protocol.MethodInfo.IsAsync;
            bool requiresSession = protocol.MethodAttribute.EnableSession;
 
            if (isAsync) {
                if (requiresSession) {
                    return new AsyncSessionHandler(protocol);
                }
                else {
                    return new AsyncSessionlessHandler(protocol);
                }
            }
            else {
                if (requiresSession) {
                    return new SyncSessionHandler(protocol);
                }
                else {
                    return new SyncSessionlessHandler(protocol);
                }
            }
        }
 
        // Asserts FullTrust permission.
        // Justification: FullTrust is used only to create the objects of type SoapServerProtocolFactory and for nothing else.
        [PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
        private ServerProtocolFactory[] GetServerProtocolFactories()
        {
            return WebServicesSection.Current.ServerProtocolFactories;
        }
 
        /// <include file='doc\WebServiceHandlerFactory.uex' path='docs/doc[@for="WebServiceHandlerFactory.ReleaseHandler"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public void ReleaseHandler(IHttpHandler handler) {
        }
    }
 
    internal class UnsupportedRequestProtocol : ServerProtocol {
        int httpCode;
 
        internal UnsupportedRequestProtocol(int httpCode) {
            this.httpCode = httpCode;
        }
        internal int HttpCode { get { return httpCode; } }
 
        internal override bool Initialize() { return true; }
 
        internal override bool IsOneWay {
            get { return false; }
        }
 
        internal override LogicalMethodInfo MethodInfo {
            get { return null; }
        }
 
        internal override ServerType ServerType {
            get { return null; }
        }
 
        internal override object[] ReadParameters() {
            return new object[0];
        }
        internal override void WriteReturns(object[] returnValues, Stream outputStream) { }
        internal override bool WriteException(Exception e, Stream outputStream) { return false; }
    }
 
    internal class NopHandler : IHttpHandler {
 
        /// <include file='doc\WebServiceHandlerFactory.uex' path='docs/doc[@for="NopHandler.IsReusable"]/*' />
        /// <devdoc>
        ///      IHttpHandler.IsReusable.
        /// </devdoc>
        public bool IsReusable {
            get { return false; }
        }
 
        /// <include file='doc\WebServiceHandlerFactory.uex' path='docs/doc[@for="NopHandler.ProcessRequest"]/*' />
        /// <devdoc>
        ///      IHttpHandler.ProcessRequest.
        /// </devdoc>
        public void ProcessRequest(HttpContext context) {
        }
 
    }
}