Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mcs / class / System.Web.Mvc / System.Web.Mvc / VirtualPathProviderViewEngine.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.Diagnostics.CodeAnalysis;\r
16     using System.Globalization;\r
17     using System.Linq;\r
18     using System.Web;\r
19     using System.Web.Hosting;\r
20     using System.Web.Mvc.Resources;\r
21 \r
22     public abstract class VirtualPathProviderViewEngine : IViewEngine {\r
23         // format is ":ViewCacheEntry:{cacheType}:{prefix}:{name}:{controllerName}:"\r
24         private const string _cacheKeyFormat = ":ViewCacheEntry:{0}:{1}:{2}:{3}:";\r
25         private const string _cacheKeyPrefix_Master = "Master";\r
26         private const string _cacheKeyPrefix_Partial = "Partial";\r
27         private const string _cacheKeyPrefix_View = "View";\r
28         private static readonly string[] _emptyLocations = new string[0];\r
29 \r
30         private VirtualPathProvider _vpp;\r
31 \r
32         [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]\r
33         public string[] MasterLocationFormats {\r
34             get;\r
35             set;\r
36         }\r
37 \r
38         [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]\r
39         public string[] PartialViewLocationFormats {\r
40             get;\r
41             set;\r
42         }\r
43 \r
44         public IViewLocationCache ViewLocationCache {\r
45             get;\r
46             set;\r
47         }\r
48 \r
49         [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]\r
50         public string[] ViewLocationFormats {\r
51             get;\r
52             set;\r
53         }\r
54 \r
55         protected VirtualPathProvider VirtualPathProvider {\r
56             get {\r
57                 if (_vpp == null) {\r
58                     _vpp = HostingEnvironment.VirtualPathProvider;\r
59                 }\r
60                 return _vpp;\r
61             }\r
62             set {\r
63                 _vpp = value;\r
64             }\r
65         }\r
66 \r
67         protected VirtualPathProviderViewEngine() {\r
68             if (HttpContext.Current == null || HttpContext.Current.IsDebuggingEnabled) {\r
69                 ViewLocationCache = DefaultViewLocationCache.Null;\r
70             }\r
71             else {\r
72                 ViewLocationCache = new DefaultViewLocationCache();\r
73             }\r
74         }\r
75 \r
76         private string CreateCacheKey(string prefix, string name, string controllerName) {\r
77             return String.Format(CultureInfo.InvariantCulture, _cacheKeyFormat,\r
78                 GetType().AssemblyQualifiedName, prefix, name, controllerName);\r
79         }\r
80 \r
81         protected abstract IView CreatePartialView(ControllerContext controllerContext, string partialPath);\r
82 \r
83         protected abstract IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath);\r
84 \r
85         protected virtual bool FileExists(ControllerContext controllerContext, string virtualPath) {\r
86             return VirtualPathProvider.FileExists(virtualPath);\r
87         }\r
88 \r
89         public virtual ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) {\r
90             if (controllerContext == null) {\r
91                 throw new ArgumentNullException("controllerContext");\r
92             }\r
93             if (String.IsNullOrEmpty(partialViewName)) {\r
94                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "partialViewName");\r
95             }\r
96 \r
97             string[] searched;\r
98             string controllerName = controllerContext.RouteData.GetRequiredString("controller");\r
99             string partialPath = GetPath(controllerContext, PartialViewLocationFormats, "PartialViewLocationFormats", partialViewName, controllerName, _cacheKeyPrefix_Partial, useCache, out searched);\r
100 \r
101             if (String.IsNullOrEmpty(partialPath)) {\r
102                 return new ViewEngineResult(searched);\r
103             }\r
104 \r
105             return new ViewEngineResult(CreatePartialView(controllerContext, partialPath), this);\r
106         }\r
107 \r
108         public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {\r
109             if (controllerContext == null) {\r
110                 throw new ArgumentNullException("controllerContext");\r
111             }\r
112             if (String.IsNullOrEmpty(viewName)) {\r
113                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "viewName");\r
114             }\r
115 \r
116             string[] viewLocationsSearched;\r
117             string[] masterLocationsSearched;\r
118 \r
119             string controllerName = controllerContext.RouteData.GetRequiredString("controller");\r
120             string viewPath = GetPath(controllerContext, ViewLocationFormats, "ViewLocationFormats", viewName, controllerName, _cacheKeyPrefix_View, useCache, out viewLocationsSearched);\r
121             string masterPath = GetPath(controllerContext, MasterLocationFormats, "MasterLocationFormats", masterName, controllerName, _cacheKeyPrefix_Master, useCache, out masterLocationsSearched);\r
122 \r
123             if (String.IsNullOrEmpty(viewPath) || (String.IsNullOrEmpty(masterPath) && !String.IsNullOrEmpty(masterName))) {\r
124                 return new ViewEngineResult(viewLocationsSearched.Union(masterLocationsSearched));\r
125             }\r
126 \r
127             return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);\r
128         }\r
129 \r
130         private string GetPath(ControllerContext controllerContext, string[] locations, string locationsPropertyName, string name, string controllerName, string cacheKeyPrefix, bool useCache, out string[] searchedLocations) {\r
131             searchedLocations = _emptyLocations;\r
132 \r
133             if (String.IsNullOrEmpty(name)) {\r
134                 return String.Empty;\r
135             }\r
136 \r
137             if (locations == null || locations.Length == 0) {\r
138                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,\r
139                     MvcResources.Common_PropertyCannotBeNullOrEmpty, locationsPropertyName));\r
140             }\r
141 \r
142             bool nameRepresentsPath = IsSpecificPath(name);\r
143             string cacheKey = CreateCacheKey(cacheKeyPrefix, name, (nameRepresentsPath) ? String.Empty : controllerName);\r
144 \r
145             if (useCache) {\r
146                 string result = ViewLocationCache.GetViewLocation(controllerContext.HttpContext, cacheKey);\r
147                 if (result != null) {\r
148                     return result;\r
149                 }\r
150             }\r
151 \r
152             return (nameRepresentsPath) ?\r
153                 GetPathFromSpecificName(controllerContext, name, cacheKey, ref searchedLocations) :\r
154                 GetPathFromGeneralName(controllerContext, locations, name, controllerName, cacheKey, ref searchedLocations);\r
155         }\r
156 \r
157         private string GetPathFromGeneralName(ControllerContext controllerContext, string[] locations, string name, string controllerName, string cacheKey, ref string[] searchedLocations) {\r
158             string result = String.Empty;\r
159             searchedLocations = new string[locations.Length];\r
160 \r
161             for (int i = 0; i < locations.Length; i++) {\r
162                 string virtualPath = String.Format(CultureInfo.InvariantCulture, locations[i], name, controllerName);\r
163 \r
164                 if (FileExists(controllerContext, virtualPath)) {\r
165                     searchedLocations = _emptyLocations;\r
166                     result = virtualPath;\r
167                     ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, cacheKey, result);\r
168                     break;\r
169                 }\r
170 \r
171                 searchedLocations[i] = virtualPath;\r
172             }\r
173 \r
174             return result;\r
175         }\r
176 \r
177         private string GetPathFromSpecificName(ControllerContext controllerContext, string name, string cacheKey, ref string[] searchedLocations) {\r
178             string result = name;\r
179 \r
180             if (!FileExists(controllerContext, name)) {\r
181                 result = String.Empty;\r
182                 searchedLocations = new[] { name };\r
183             }\r
184 \r
185             ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, cacheKey, result);\r
186             return result;\r
187         }\r
188 \r
189         private static bool IsSpecificPath(string name) {\r
190             char c = name[0];\r
191             return (c == '~' || c == '/');\r
192         }\r
193 \r
194         public virtual void ReleaseView(ControllerContext controllerContext, IView view) {\r
195             IDisposable disposable = view as IDisposable;\r
196             if (disposable != null) {\r
197                 disposable.Dispose();\r
198             }\r
199         }\r
200     }\r
201 }