File: ServiceRouteHandler.cs

package info (click to toggle)
mono 4.6.2.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 778,148 kB
  • ctags: 914,052
  • sloc: cs: 5,779,509; xml: 2,773,713; ansic: 432,645; sh: 14,749; makefile: 12,361; perl: 2,488; python: 1,434; cpp: 849; asm: 531; sql: 95; sed: 16; php: 1
file content (129 lines) | stat: -rw-r--r-- 5,238 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------

namespace System.ServiceModel.Activation
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.Linq;
    using System.Runtime;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Diagnostics.Application;
    using System.Web;
    using System.Web.Hosting;
    using System.Web.Routing;

    class ServiceRouteHandler : IRouteHandler
    {
        string baseAddress;

        // Double-checked locking pattern requires volatile for read/write synchronization
        volatile IHttpHandler handler;
        object locker = new object();
        [Fx.Tag.Cache(
                typeof(ServiceDeploymentInfo),
                Fx.Tag.CacheAttrition.None,
                Scope = "instance of declaring class",
                SizeLimit = "unbounded",
                Timeout = "infinite"
                )]
        static Hashtable routeServiceTable = new Hashtable(StringComparer.CurrentCultureIgnoreCase);

        public ServiceRouteHandler(string baseAddress, ServiceHostFactoryBase serviceHostFactory, Type webServiceType)
        {
            this.baseAddress = string.Format(CultureInfo.CurrentCulture, "~/{0}", baseAddress);
            if (webServiceType == null)
            {
                throw FxTrace.Exception.AsError(new ArgumentNullException("webServiceType"));
            }
            if (serviceHostFactory == null)
            {
                throw FxTrace.Exception.AsError(new ArgumentNullException("serviceHostFactory"));
            }
            string serviceType = webServiceType.AssemblyQualifiedName;

            AddServiceInfo(this.baseAddress, new ServiceDeploymentInfo(this.baseAddress, serviceHostFactory, serviceType));
        }

        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            // we create httphandler only we the request map to the corresponding route.
            // we thus do not need to check whether the baseAddress has been added  
            // even though Asp.Net allows duplicated routes but it picks the first match 
            if (handler == null)
            {
                // use local lock to prevent multiple httphanders from being created
                lock (locker)
                {
                    if (handler == null)
                    {
                        IHttpHandler tempHandler = new AspNetRouteServiceHttpHandler(this.baseAddress);
                        MarkRouteAsActive(this.baseAddress);
                        handler = tempHandler;
                    }
                }
            }
            return handler;
        }

        static void AddServiceInfo(string virtualPath, ServiceDeploymentInfo serviceInfo)
        {
            Fx.Assert(!string.IsNullOrEmpty(virtualPath), "virtualPath should not be empty or null");
            Fx.Assert(serviceInfo != null, "serviceInfo should not be null");
            // We cannot support dulicated route routes even Asp.Net route allows it
            try
            {
                routeServiceTable.Add(virtualPath, serviceInfo);
            }
            catch (ArgumentException)
            {
                throw FxTrace.Exception.Argument("virtualPath", SR.Hosting_RouteHasAlreadyBeenAdded(virtualPath));
            }
        }

        public static ServiceDeploymentInfo GetServiceInfo(string normalizedVirtualPath)
        {
            return (ServiceDeploymentInfo)routeServiceTable[normalizedVirtualPath];
        }

        public static bool IsActiveAspNetRoute(string virtualPath)
        {
            bool isRouteService = false;
            if (!string.IsNullOrEmpty(virtualPath))
            {
                ServiceDeploymentInfo serviceInfo = (ServiceDeploymentInfo)routeServiceTable[virtualPath];
                if (serviceInfo != null)
                {
                    isRouteService = serviceInfo.MessageHandledByRoute;
                }
            }
            return isRouteService;
        }       

        // A route in routetable does not always mean the route will be picked
        // we update IsRouteService only when Asp.Net picks this route
        public static void MarkRouteAsActive(string normalizedVirtualPath)
        {
            ServiceDeploymentInfo serviceInfo = (ServiceDeploymentInfo)routeServiceTable[normalizedVirtualPath];
            if (serviceInfo != null)
            {
                serviceInfo.MessageHandledByRoute = true;
            }
        }
        // a route should be marked as inactive in the case that CBA should be used
        public static void MarkARouteAsInactive(string normalizedVirtualPath)
        {
            ServiceDeploymentInfo serviceInfo = (ServiceDeploymentInfo)routeServiceTable[normalizedVirtualPath];
            if (serviceInfo != null)
            {
                serviceInfo.MessageHandledByRoute = false;
            }
        }
    }
}