2 // System.Web.Compilation.TemplateBuildProvider
5 // Marek Habersack (mhabersack@novell.com)
7 // (C) 2007 Novell, Inc
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.CodeDom.Compiler;
34 using System.Collections;
35 using System.Collections.Generic;
37 using System.Reflection;
38 using System.Text.RegularExpressions;
40 using System.Web.Hosting;
42 using System.Web.Util;
44 namespace System.Web.Compilation
46 internal abstract class TemplateBuildProvider : GenericBuildProvider <TemplateParser>
48 delegate void ExtractDirectiveDependencies (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp);
50 static SortedDictionary <string, ExtractDirectiveDependencies> directiveAttributes;
51 static char[] directiveValueTrimChars = {' ', '\t', '\r', '\n', '"', '\''};
53 SortedDictionary <string, bool> dependencies;
54 string compilationLanguage;
56 internal override string LanguageName {
58 if (String.IsNullOrEmpty (compilationLanguage)) {
59 ExtractDependencies ();
60 if (String.IsNullOrEmpty (compilationLanguage))
61 compilationLanguage = base.LanguageName;
64 return compilationLanguage;
68 static TemplateBuildProvider ()
70 directiveAttributes = new SortedDictionary <string, ExtractDirectiveDependencies> (StringComparer.InvariantCultureIgnoreCase);
71 directiveAttributes.Add ("Control", ExtractControlDependencies);
72 directiveAttributes.Add ("Master", ExtractPageOrMasterDependencies);
73 directiveAttributes.Add ("MasterType", ExtractPreviousPageTypeOrMasterTypeDependencies);
74 directiveAttributes.Add ("Page", ExtractPageOrMasterDependencies);
75 directiveAttributes.Add ("PreviousPageType", ExtractPreviousPageTypeOrMasterTypeDependencies);
76 directiveAttributes.Add ("Reference", ExtractReferenceDependencies);
77 directiveAttributes.Add ("Register", ExtractRegisterDependencies);
78 directiveAttributes.Add ("WebHandler", ExtractLanguage);
79 directiveAttributes.Add ("WebService", ExtractLanguage);
82 static string ExtractDirectiveAttribute (string baseDirectory, string name, CaptureCollection names, CaptureCollection values)
84 return ExtractDirectiveAttribute (baseDirectory, name, names, values, true);
87 static string ExtractDirectiveAttribute (string baseDirectory, string name, CaptureCollection names, CaptureCollection values, bool isPath)
93 int valuesCount = values.Count;
94 foreach (Capture c in names) {
95 if (String.Compare (c.Value, name, StringComparison.OrdinalIgnoreCase) != 0) {
100 if (index > valuesCount)
104 return new VirtualPath (values [index].Value.Trim (directiveValueTrimChars), baseDirectory).Absolute;
106 return values [index].Value.Trim ();
112 static void ExtractControlDependencies (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp)
114 ExtractLanguage (baseDirectory, names, values, bp);
115 ExtractCodeBehind (baseDirectory, names, values, bp);
118 static void ExtractLanguage (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp)
120 string value = ExtractDirectiveAttribute (baseDirectory, "Language", names, values, false);
121 if (String.IsNullOrEmpty (value))
124 bp.compilationLanguage = value;
126 ExtractCodeBehind (baseDirectory, names, values, bp);
129 static void ExtractPageOrMasterDependencies (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp)
131 ExtractLanguage (baseDirectory, names, values, bp);
132 string value = ExtractDirectiveAttribute (baseDirectory, "MasterPageFile", names, values);
133 if (!String.IsNullOrEmpty (value)) {
134 if (!bp.dependencies.ContainsKey (value))
135 bp.dependencies.Add (value, true);
138 ExtractCodeBehind (baseDirectory, names, values, bp);
141 static void ExtractCodeBehind (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp)
143 string[] varray = new string [2];
145 varray [0] = ExtractDirectiveAttribute (baseDirectory, "CodeFile", names, values);
146 varray [1] = ExtractDirectiveAttribute (baseDirectory, "Src", names, values);
147 foreach (string value in varray) {
148 if (!String.IsNullOrEmpty (value)) {
149 if (!bp.dependencies.ContainsKey (value))
150 bp.dependencies.Add (value, true);
155 static void ExtractRegisterDependencies (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp)
157 string src = ExtractDirectiveAttribute (baseDirectory, "Src", names, values);
158 if (String.IsNullOrEmpty (src))
161 string value = ExtractDirectiveAttribute (baseDirectory, "TagName", names, values);
162 if (String.IsNullOrEmpty (value))
165 value = ExtractDirectiveAttribute (baseDirectory, "TagPrefix", names, values);
166 if (String.IsNullOrEmpty (value))
169 if (bp.dependencies.ContainsKey (src))
172 bp.dependencies.Add (src, true);
175 static void ExtractPreviousPageTypeOrMasterTypeDependencies (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp)
177 string value = ExtractDirectiveAttribute (baseDirectory, "VirtualPath", names, values);
178 if (String.IsNullOrEmpty (value))
181 if (bp.dependencies.ContainsKey (value))
184 bp.dependencies.Add (value, true);
187 static void ExtractReferenceDependencies (string baseDirectory, CaptureCollection names, CaptureCollection values, TemplateBuildProvider bp)
189 string control = ExtractDirectiveAttribute (baseDirectory, "Control", names, values);
190 string virtualPath = ExtractDirectiveAttribute (baseDirectory, "VirtualPath", names, values);
191 string page = ExtractDirectiveAttribute (baseDirectory, "Page", names, values);
192 bool controlEmpty = String.IsNullOrEmpty (control);
193 bool virtualPathEmpty = String.IsNullOrEmpty (virtualPath);
194 bool pageEmpty = String.IsNullOrEmpty (page);
196 if (controlEmpty && virtualPathEmpty && pageEmpty)
199 if ((controlEmpty ? 1 : 0) + (virtualPathEmpty ? 1 : 0) + (pageEmpty ? 1 : 0) != 2)
205 else if (!virtualPathEmpty)
210 if (bp.dependencies.ContainsKey (value))
213 bp.dependencies.Add (value, true);
216 internal override IDictionary <string, bool> ExtractDependencies ()
218 if (dependencies != null) {
219 if (dependencies.Count == 0)
224 string vpath = VirtualPath;
225 if (String.IsNullOrEmpty (vpath))
228 VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
229 if (!vpp.FileExists (vpath))
232 VirtualFile vf = vpp.GetFile (vpath);
237 using (Stream st = vf.Open ()) {
238 if (st == null || !st.CanRead)
241 using (StreamReader sr = new StreamReader (st, WebEncoding.FileEncoding)) {
242 input = sr.ReadToEnd ();
246 if (String.IsNullOrEmpty (input))
249 MatchCollection matches = AspGenerator.DirectiveRegex.Matches (input);
250 if (matches == null || matches.Count == 0)
253 dependencies = new SortedDictionary <string, bool> (StringComparer.InvariantCultureIgnoreCase);
254 CaptureCollection ccNames;
255 GroupCollection groups;
256 string directiveName;
257 ExtractDirectiveDependencies edd;
258 string baseDirectory = VirtualPathUtility.GetDirectory (vpath);
260 foreach (Match match in matches) {
261 groups = match.Groups;
262 if (groups.Count < 6)
265 ccNames = groups [3].Captures;
266 directiveName = ccNames [0].Value;
267 if (!directiveAttributes.TryGetValue (directiveName, out edd))
269 edd (baseDirectory, ccNames, groups [5].Captures, this);
272 if (dependencies.Count == 0)
278 protected override string GetClassType (BaseCompiler compiler, TemplateParser parser)
280 if (compiler != null)
281 return compiler.MainClassType;
286 protected override ICollection GetParserDependencies (TemplateParser parser)
289 return parser.Dependencies;
294 protected override string GetParserLanguage (TemplateParser parser)
297 return parser.Language;
302 protected override string GetCodeBehindSource (TemplateParser parser)
304 if (parser != null) {
305 string codeBehind = parser.CodeBehindSource;
306 if (String.IsNullOrEmpty (codeBehind))
309 return parser.CodeBehindSource;
315 protected override AspGenerator CreateAspGenerator (TemplateParser parser)
318 return new AspGenerator (parser);
323 protected override List <string> GetReferencedAssemblies (TemplateParser parser)
328 ArrayList al = parser.Assemblies;
329 if (al == null || al.Count == 0)
332 List <string> ret = new List <string> ();
335 foreach (object o in al) {
340 if (ret.Contains (loc))