Remove excessive shortcut key matching in ToolStrip
[mono.git] / mcs / class / System.Web.Mvc / System.Web.Mvc / DefaultControllerFactory.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\r
5  * This software is subject to the Microsoft Public License (Ms-PL). \r
6  * A copy of the license can be found in the license.htm file included \r
7  * in this distribution.\r
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc {\r
14     using System;\r
15     using System.Collections;\r
16     using System.Collections.Generic;\r
17     using System.Globalization;\r
18     using System.Text;\r
19     using System.Web;\r
20     using System.Web.Mvc.Resources;\r
21     using System.Web.Routing;\r
22 \r
23     public class DefaultControllerFactory : IControllerFactory {\r
24 \r
25         private IBuildManager _buildManager;\r
26         private ControllerBuilder _controllerBuilder;\r
27         private ControllerTypeCache _instanceControllerTypeCache;\r
28         private static ControllerTypeCache _staticControllerTypeCache = new ControllerTypeCache();\r
29 \r
30         internal IBuildManager BuildManager {\r
31             get {\r
32                 if (_buildManager == null) {\r
33                     _buildManager = new BuildManagerWrapper();\r
34                 }\r
35                 return _buildManager;\r
36             }\r
37             set {\r
38                 _buildManager = value;\r
39             }\r
40         }\r
41 \r
42         internal ControllerBuilder ControllerBuilder {\r
43             get {\r
44                 return _controllerBuilder ?? ControllerBuilder.Current;\r
45             }\r
46             set {\r
47                 _controllerBuilder = value;\r
48             }\r
49         }\r
50 \r
51         internal ControllerTypeCache ControllerTypeCache {\r
52             get {\r
53                 return _instanceControllerTypeCache ?? _staticControllerTypeCache;\r
54             }\r
55             set {\r
56                 _instanceControllerTypeCache = value;\r
57             }\r
58         }\r
59 \r
60         public RequestContext RequestContext {\r
61             get;\r
62             set;\r
63         }\r
64 \r
65         public virtual IController CreateController(RequestContext requestContext, string controllerName) {\r
66             if (requestContext == null) {\r
67                 throw new ArgumentNullException("requestContext");\r
68             }\r
69             if (String.IsNullOrEmpty(controllerName)) {\r
70                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");\r
71             }\r
72             RequestContext = requestContext;\r
73             Type controllerType = GetControllerType(controllerName);\r
74             IController controller = GetControllerInstance(controllerType);\r
75             return controller;\r
76         }\r
77 \r
78         protected internal virtual IController GetControllerInstance(Type controllerType) {\r
79             if (controllerType == null) {\r
80                 throw new HttpException(404,\r
81                     String.Format(\r
82                         CultureInfo.CurrentUICulture,\r
83                         MvcResources.DefaultControllerFactory_NoControllerFound,\r
84                         RequestContext.HttpContext.Request.Path));\r
85             }\r
86             if (!typeof(IController).IsAssignableFrom(controllerType)) {\r
87                 throw new ArgumentException(\r
88                     String.Format(\r
89                         CultureInfo.CurrentUICulture,\r
90                         MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase,\r
91                         controllerType),\r
92                     "controllerType");\r
93             }\r
94             try {\r
95                 return (IController)Activator.CreateInstance(controllerType);\r
96             }\r
97             catch (Exception ex) {\r
98                 throw new InvalidOperationException(\r
99                     String.Format(\r
100                         CultureInfo.CurrentUICulture,\r
101                         MvcResources.DefaultControllerFactory_ErrorCreatingController,\r
102                         controllerType),\r
103                     ex);\r
104             }\r
105         }\r
106 \r
107         protected internal virtual Type GetControllerType(string controllerName) {\r
108             if (String.IsNullOrEmpty(controllerName)) {\r
109                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");\r
110             }\r
111 \r
112             // first search in the current route's namespace collection\r
113             object routeNamespacesObj;\r
114             Type match;\r
115             if (RequestContext != null && RequestContext.RouteData.DataTokens.TryGetValue("Namespaces", out routeNamespacesObj)) {\r
116                 IEnumerable<string> routeNamespaces = routeNamespacesObj as IEnumerable<string>;\r
117                 if (routeNamespaces != null) {\r
118                     HashSet<string> nsHash = new HashSet<string>(routeNamespaces, StringComparer.OrdinalIgnoreCase);\r
119                     match = GetControllerTypeWithinNamespaces(controllerName, nsHash);\r
120                     if (match != null) {\r
121                         return match;\r
122                     }\r
123                 }\r
124             }\r
125 \r
126             // then search in the application's default namespace collection\r
127             HashSet<string> nsDefaults = new HashSet<string>(ControllerBuilder.DefaultNamespaces, StringComparer.OrdinalIgnoreCase);\r
128             match = GetControllerTypeWithinNamespaces(controllerName, nsDefaults);\r
129             if (match != null) {\r
130                 return match;\r
131             }\r
132 \r
133             // if all else fails, search every namespace\r
134             return GetControllerTypeWithinNamespaces(controllerName, null /* namespaces */);\r
135         }\r
136 \r
137         private Type GetControllerTypeWithinNamespaces(string controllerName, HashSet<string> namespaces) {\r
138             // Once the master list of controllers has been created we can quickly index into it\r
139             ControllerTypeCache.EnsureInitialized(BuildManager);\r
140 \r
141             IList<Type> matchingTypes = ControllerTypeCache.GetControllerTypes(controllerName, namespaces);\r
142             switch (matchingTypes.Count) {\r
143                 case 0:\r
144                     // no matching types\r
145                     return null;\r
146 \r
147                 case 1:\r
148                     // single matching type\r
149                     return matchingTypes[0];\r
150 \r
151                 default:\r
152                     // multiple matching types\r
153                     // we need to generate an exception containing all the controller types\r
154                     StringBuilder sb = new StringBuilder();\r
155                     foreach (Type matchedType in matchingTypes) {\r
156                         sb.AppendLine();\r
157                         sb.Append(matchedType.FullName);\r
158                     }\r
159                     throw new InvalidOperationException(\r
160                         String.Format(\r
161                             CultureInfo.CurrentUICulture,\r
162                             MvcResources.DefaultControllerFactory_ControllerNameAmbiguous,\r
163                             controllerName, sb));\r
164             }\r
165         }\r
166 \r
167         public virtual void ReleaseController(IController controller) {\r
168             IDisposable disposable = controller as IDisposable;\r
169             if (disposable != null) {\r
170                 disposable.Dispose();\r
171             }\r
172         }\r
173     }\r
174 }\r