2 // System.Web.UI.TemplateParser
5 // Duncan Mak (duncan@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Marek Habersack (mhabersack@novell.com)
9 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.CodeDom.Compiler;
33 using System.Collections;
34 using System.Collections.Generic;
35 using System.ComponentModel;
36 using System.Globalization;
38 using System.Reflection;
39 using System.Security.Permissions;
41 using System.Threading;
42 using System.Web.Compilation;
43 using System.Web.Hosting;
44 using System.Web.Configuration;
45 using System.Web.Util;
47 namespace System.Web.UI {
48 internal class ServerSideScript
50 public readonly string Script;
51 public readonly ILocation Location;
53 public ServerSideScript (string script, ILocation location)
61 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
62 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
63 public abstract class TemplateParser : BaseParser
66 internal enum OutputCacheParsedParams
69 CacheProfile = 0x0002,
71 SqlDependency = 0x0008,
72 VaryByCustom = 0x0010,
73 VaryByHeader = 0x0020,
74 VaryByControl = 0x0040,
75 VaryByContentEncodings = 0x0080
80 IDictionary mainAttributes;
81 List <string> dependencies;
82 List <string> assemblies;
84 string[] binDirAssemblies;
85 Dictionary <string, bool> namespacesCache;
86 Dictionary <string, bool> imports;
87 List <string> interfaces;
88 List <ServerSideScript> scripts;
90 bool baseTypeIsGlobal = true;
92 RootBuilder rootBuilder;
94 string compilerOptions;
96 bool implicitLanguage;
99 bool linePragmasOn = true;
102 string oc_header, oc_custom, oc_param, oc_controls;
103 string oc_content_encodings, oc_cacheprofile, oc_sqldependency;
105 OutputCacheParsedParams oc_parsed_params = 0;
107 OutputCacheLocation oc_location;
109 // Kludge needed to support pre-parsing of the main directive (see
110 // AspNetGenerator.GetRootBuilderType)
111 internal int allowedMainDirectives = 0;
116 string partialClassName;
117 string codeFileBaseClass;
118 string metaResourceKey;
119 Type codeFileBaseClassType;
120 Type pageParserFilterType;
121 PageParserFilter pageParserFilter;
123 List <UnknownAttributeDescriptor> unknownMainAttributes;
124 Stack <string> includeDirs;
125 List <string> registeredTagNames;
126 ILocation directiveLocation;
128 int appAssemblyIndex = -1;
130 internal TemplateParser ()
132 imports = new Dictionary <string, bool> (StringComparer.Ordinal);
133 LoadConfigDefaults ();
134 assemblies = new List <string> ();
135 CompilationSection compConfig = CompilationConfig;
136 foreach (AssemblyInfo info in compConfig.Assemblies) {
137 if (info.Assembly != "*")
138 AddAssemblyByName (info.Assembly);
141 language = compConfig.DefaultLanguage;
142 implicitLanguage = true;
145 internal virtual void LoadConfigDefaults ()
147 AddNamespaces (imports);
148 debug = CompilationConfig.Debug;
151 internal void AddApplicationAssembly ()
153 if (Context.ApplicationInstance == null)
154 return; // this may happen if we have Global.asax and have
155 // controls registered from Web.Config
156 string location = Context.ApplicationInstance.AssemblyLocation;
157 if (location != typeof (TemplateParser).Assembly.Location) {
158 assemblies.Add (location);
159 appAssemblyIndex = assemblies.Count - 1;
163 internal abstract Type CompileIntoType ();
165 internal void AddControl (Type type, IDictionary attributes)
167 AspGenerator generator = AspGenerator;
168 if (generator == null)
170 generator.AddControl (type, attributes);
173 void AddNamespaces (Dictionary <string, bool> imports)
175 if (BuildManager.HaveResources)
176 imports.Add ("System.Resources", true);
178 PagesSection pages = PagesConfig;
182 NamespaceCollection namespaces = pages.Namespaces;
183 if (namespaces == null || namespaces.Count == 0)
186 foreach (NamespaceInfo nsi in namespaces) {
187 string ns = nsi.Namespace;
188 if (imports.ContainsKey (ns))
191 imports.Add (ns, true);
195 internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
197 string realpath = null;
198 bool fileExists = false;
199 VirtualFile vf = null;
200 VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
201 VirtualPath vp = new VirtualPath (src, BaseVirtualDir);
202 string vpAbsolute = vpp.CombineVirtualPaths (VirtualPath.Absolute, vp.Absolute);
204 if (vpp.FileExists (vpAbsolute)) {
206 vf = vpp.GetFile (vpAbsolute);
208 realpath = MapPath (vf.VirtualPath);
212 ThrowParseFileNotFound (src);
214 if (String.Compare (realpath, inputFile, StringComparison.Ordinal) == 0)
217 string vpath = vf.VirtualPath;
220 RegisterTagName (tagPrefix + ":" + tagName);
221 RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, vpath);
222 AddDependency (vpath);
223 } catch (ParseException pe) {
224 if (this is UserControlParser)
225 throw new ParseException (Location, pe.Message, pe);
230 internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
235 if (assembly != null && assembly.Length > 0)
236 ass = AddAssemblyByName (assembly);
238 RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
241 internal virtual void HandleOptions (object obj)
245 internal static string GetOneKey (IDictionary tbl)
247 foreach (object key in tbl.Keys)
248 return key.ToString ();
253 internal virtual void AddDirective (string directive, IDictionary atts)
255 var pageParserFilter = PageParserFilter;
256 if (String.Compare (directive, DefaultDirectiveName, true, Helpers.InvariantCulture) == 0) {
257 bool allowMainDirective = allowedMainDirectives > 0;
259 if (mainAttributes != null && !allowMainDirective)
260 ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
262 allowedMainDirectives--;
263 if (mainAttributes != null)
266 if (pageParserFilter != null)
267 pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
269 mainAttributes = atts;
270 ProcessMainAttributes (mainAttributes);
272 } else if (pageParserFilter != null)
273 pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
275 int cmp = String.Compare ("Assembly", directive, true, Helpers.InvariantCulture);
277 string name = GetString (atts, "Name", null);
278 string src = GetString (atts, "Src", null);
281 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
283 if (name == null && src == null)
284 ThrowParseException ("You gotta specify Src or Name");
286 if (name != null && src != null)
287 ThrowParseException ("Src and Name cannot be used together");
290 AddAssemblyByName (name);
292 GetAssemblyFromSource (src);
298 cmp = String.Compare ("Import", directive, true, Helpers.InvariantCulture);
300 string namesp = GetString (atts, "Namespace", null);
302 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
308 cmp = String.Compare ("Implements", directive, true, Helpers.InvariantCulture);
310 string ifacename = GetString (atts, "Interface", "");
313 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
315 Type iface = LoadType (ifacename);
317 ThrowParseException ("Cannot find type " + ifacename);
319 if (!iface.IsInterface)
320 ThrowParseException (iface + " is not an interface");
322 AddInterface (iface.FullName);
326 cmp = String.Compare ("OutputCache", directive, true, Helpers.InvariantCulture);
328 HttpResponse response = HttpContext.Current.Response;
329 if (response != null)
330 response.Cache.SetValidUntilExpires (true);
333 ProcessOutputCacheAttributes (atts);
337 ThrowParseException ("Unknown directive: " + directive);
340 internal virtual void ProcessOutputCacheAttributes (IDictionary atts)
342 if (atts ["Duration"] == null)
343 ThrowParseException ("The directive is missing a 'duration' attribute.");
344 if (atts ["VaryByParam"] == null && atts ["VaryByControl"] == null)
345 ThrowParseException ("This directive is missing 'VaryByParam' " +
346 "or 'VaryByControl' attribute, which should be set to \"none\", \"*\", " +
347 "or a list of name/value pairs.");
349 foreach (DictionaryEntry entry in atts) {
350 string key = (string) entry.Key;
354 switch (key.ToLower (Helpers.InvariantCulture)) {
356 oc_duration = Int32.Parse ((string) entry.Value);
358 ThrowParseException ("The 'duration' attribute must be set " +
359 "to a positive integer value");
362 case "sqldependency":
363 oc_sqldependency = (string) entry.Value;
368 oc_nostore = Boolean.Parse ((string) entry.Value);
369 oc_parsed_params |= OutputCacheParsedParams.NoStore;
371 ThrowParseException ("The 'NoStore' attribute is case sensitive" +
372 " and must be set to 'true' or 'false'.");
377 oc_cacheprofile = (string) entry.Value;
378 oc_parsed_params |= OutputCacheParsedParams.CacheProfile;
381 case "varybycontentencodings":
382 oc_content_encodings = (string) entry.Value;
383 oc_parsed_params |= OutputCacheParsedParams.VaryByContentEncodings;
387 oc_param = (string) entry.Value;
388 if (String.Compare (oc_param, "none", true, Helpers.InvariantCulture) == 0)
392 oc_header = (string) entry.Value;
393 oc_parsed_params |= OutputCacheParsedParams.VaryByHeader;
396 oc_custom = (string) entry.Value;
397 oc_parsed_params |= OutputCacheParsedParams.VaryByCustom;
400 if (!(this is PageParser))
404 oc_location = (OutputCacheLocation) Enum.Parse (
405 typeof (OutputCacheLocation), (string) entry.Value, true);
406 oc_parsed_params |= OutputCacheParsedParams.Location;
408 ThrowParseException ("The 'location' attribute is case sensitive and " +
409 "must be one of the following values: Any, Client, " +
410 "Downstream, Server, None, ServerAndClient.");
413 case "varybycontrol":
414 oc_controls = (string) entry.Value;
415 oc_parsed_params |= OutputCacheParsedParams.VaryByControl;
418 if (this is PageParser)
422 oc_shared = Boolean.Parse ((string) entry.Value);
424 ThrowParseException ("The 'shared' attribute is case sensitive" +
425 " and must be set to 'true' or 'false'.");
429 ThrowParseException ("The '" + key + "' attribute is not " +
430 "supported by the 'Outputcache' directive.");
437 internal Type LoadType (string typeName)
439 Type type = HttpApplication.LoadType (typeName);
442 Assembly asm = type.Assembly;
443 string location = asm.Location;
445 string dirname = Path.GetDirectoryName (location);
446 bool doAddAssembly = true;
447 if (dirname == HttpApplication.BinDirectory)
448 doAddAssembly = false;
451 AddAssembly (asm, true);
456 internal virtual void AddInterface (string iface)
458 if (interfaces == null)
459 interfaces = new List <string> ();
461 if (!interfaces.Contains (iface))
462 interfaces.Add (iface);
465 internal virtual void AddImport (string namesp)
467 if (namesp == null || namesp.Length == 0)
471 imports = new Dictionary <string, bool> (StringComparer.Ordinal);
473 if (imports.ContainsKey (namesp))
476 imports.Add (namesp, true);
477 AddAssemblyForNamespace (namesp);
480 void AddAssemblyForNamespace (string namesp)
482 if (binDirAssemblies == null)
483 binDirAssemblies = HttpApplication.BinDirectoryAssemblies;
484 if (binDirAssemblies.Length == 0)
487 if (namespacesCache == null)
488 namespacesCache = new Dictionary <string, bool> ();
489 else if (namespacesCache.ContainsKey (namesp))
492 foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
493 if (FindNamespaceInAssembly (asm, namesp))
496 IList tla = BuildManager.TopLevelAssemblies;
497 if (tla != null && tla.Count > 0) {
498 foreach (Assembly asm in tla) {
499 if (FindNamespaceInAssembly (asm, namesp))
505 foreach (string s in binDirAssemblies) {
506 a = Assembly.LoadFrom (s);
507 if (FindNamespaceInAssembly (a, namesp))
512 bool FindNamespaceInAssembly (Assembly asm, string namesp)
517 asmTypes = asm.GetTypes ();
518 } catch (ReflectionTypeLoadException) {
523 foreach (Type type in asmTypes) {
524 if (String.Compare (type.Namespace, namesp, StringComparison.Ordinal) == 0) {
525 namespacesCache.Add (namesp, true);
526 AddAssembly (asm, true);
534 internal virtual void AddSourceDependency (string filename)
536 if (dependencies != null && dependencies.Contains (filename))
537 ThrowParseException ("Circular file references are not allowed. File: " + filename);
539 AddDependency (filename);
542 internal virtual void AddDependency (string filename)
544 AddDependency (filename, true);
547 internal virtual void AddDependency (string filename, bool combinePaths)
549 if (String.IsNullOrEmpty (filename))
552 if (dependencies == null)
553 dependencies = new List <string> ();
556 filename = HostingEnvironment.VirtualPathProvider.CombineVirtualPaths (VirtualPath.Absolute, filename);
558 if (!dependencies.Contains (filename))
559 dependencies.Add (filename);
562 internal virtual void AddAssembly (Assembly assembly, bool fullPath)
564 if (assembly == null || assembly.Location == String.Empty)
568 anames = new Dictionary <string, object> ();
570 string name = assembly.GetName ().Name;
571 string loc = assembly.Location;
573 if (!assemblies.Contains (loc)) {
574 assemblies.Add (loc);
578 anames [loc] = assembly;
580 if (!assemblies.Contains (name)) {
581 assemblies.Add (name);
584 anames [name] = assembly;
588 internal virtual Assembly AddAssemblyByFileName (string filename)
590 Assembly assembly = null;
591 Exception error = null;
594 assembly = Assembly.LoadFrom (filename);
595 } catch (Exception e) { error = e; }
597 if (assembly == null)
598 ThrowParseException ("Assembly " + filename + " not found", error);
600 AddAssembly (assembly, true);
604 internal virtual Assembly AddAssemblyByName (string name)
607 anames = new Dictionary <string, object> ();
609 if (anames.Contains (name)) {
610 object o = anames [name];
617 Assembly assembly = null;
618 Exception error = null;
620 assembly = Assembly.Load (name);
621 } catch (Exception e) { error = e; }
623 if (assembly == null) {
625 assembly = Assembly.LoadWithPartialName (name);
626 } catch (Exception e) { error = e; }
629 if (assembly == null)
630 ThrowParseException ("Assembly " + name + " not found", error);
632 AddAssembly (assembly, true);
636 internal virtual void ProcessMainAttributes (IDictionary atts)
638 directiveLocation = new System.Web.Compilation.Location (Location);
639 CompilationSection compConfig;
641 compConfig = CompilationConfig;
643 atts.Remove ("Description"); // ignored
644 atts.Remove ("CodeBehind"); // ignored
645 atts.Remove ("AspCompat"); // ignored
647 debug = GetBool (atts, "Debug", compConfig.Debug);
648 compilerOptions = GetString (atts, "CompilerOptions", String.Empty);
649 language = GetString (atts, "Language", "");
650 if (language.Length != 0)
651 implicitLanguage = false;
653 language = compConfig.DefaultLanguage;
655 strictOn = GetBool (atts, "Strict", compConfig.Strict);
656 explicitOn = GetBool (atts, "Explicit", compConfig.Explicit);
657 if (atts.Contains ("LinePragmas"))
658 linePragmasOn = GetBool (atts, "LinePragmas", true);
660 string inherits = GetString (atts, "Inherits", null);
661 string srcRealPath = null;
663 // In ASP 2+, the source file is actually integrated with
664 // the generated file via the use of partial classes. This
665 // means that the code file has to be confirmed, but not
666 // used at this point.
667 src = GetString (atts, "CodeFile", null);
668 codeFileBaseClass = GetString (atts, "CodeFileBaseClass", null);
670 if (src == null && codeFileBaseClass != null)
671 ThrowParseException ("The 'CodeFileBaseClass' attribute cannot be used without a 'CodeFile' attribute");
673 string legacySrc = GetString (atts, "Src", null);
674 var vpp = HostingEnvironment.VirtualPathProvider;
675 if (legacySrc != null) {
676 legacySrc = vpp.CombineVirtualPaths (BaseVirtualDir, legacySrc);
677 GetAssemblyFromSource (legacySrc);
681 legacySrc = MapPath (legacySrc, false);
682 srcRealPath = legacySrc;
683 if (!File.Exists (srcRealPath))
684 ThrowParseException ("File " + src + " not found");
688 legacySrc = MapPath (legacySrc, false);
690 AddDependency (legacySrc, false);
693 if (!srcIsLegacy && src != null && inherits != null) {
694 // Make sure the source exists
695 src = vpp.CombineVirtualPaths (BaseVirtualDir, src);
696 srcRealPath = MapPath (src, false);
698 if (!vpp.FileExists (src))
699 ThrowParseException ("File " + src + " not found");
701 // We are going to create a partial class that shares
702 // the same name as the inherits tag, so reset the
703 // name. The base type is changed because it is the
704 // code file's responsibilty to extend the classes
706 partialClassName = inherits;
708 // Add the code file as an option to the
709 // compiler. This lets both files be compiled at once.
710 compilerOptions += " \"" + srcRealPath + "\"";
712 if (codeFileBaseClass != null) {
714 codeFileBaseClassType = LoadType (codeFileBaseClass);
715 } catch (Exception) {
718 if (codeFileBaseClassType == null)
719 ThrowParseException ("Could not load type '{0}'", codeFileBaseClass);
721 } else if (inherits != null) {
722 // We just set the inherits directly because this is a
723 // Single-Page model.
724 SetBaseType (inherits);
728 if (VirtualPathUtility.IsAbsolute (src))
729 src = VirtualPathUtility.ToAppRelative (src);
730 AddDependency (src, false);
733 className = GetString (atts, "ClassName", null);
734 if (className != null) {
735 string [] identifiers = className.Split ('.');
736 for (int i = 0; i < identifiers.Length; i++)
737 if (!CodeGenerator.IsValidLanguageIndependentIdentifier (identifiers [i]))
738 ThrowParseException (String.Format ("'{0}' is not a valid "
739 + "value for attribute 'classname'.", className));
742 if (this is TemplateControlParser)
743 metaResourceKey = GetString (atts, "meta:resourcekey", null);
745 if (inherits != null && (this is PageParser || this is UserControlParser) && atts.Count > 0) {
746 if (unknownMainAttributes == null)
747 unknownMainAttributes = new List <UnknownAttributeDescriptor> ();
750 foreach (DictionaryEntry de in atts) {
751 key = de.Key as string;
752 val = de.Value as string;
754 if (String.IsNullOrEmpty (key) || String.IsNullOrEmpty (val))
756 CheckUnknownAttribute (key, val, inherits);
762 ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
765 void RegisterTagName (string tagName)
767 if (registeredTagNames == null)
768 registeredTagNames = new List <string> ();
770 if (registeredTagNames.Contains (tagName))
773 registeredTagNames.Add (tagName);
776 void CheckUnknownAttribute (string name, string val, string inherits)
778 MemberInfo mi = null;
779 bool missing = false;
780 string memberName = name.Trim ().ToLower (Helpers.InvariantCulture);
781 Type parent = codeFileBaseClassType;
787 MemberInfo[] infos = parent.GetMember (memberName,
788 MemberTypes.Field | MemberTypes.Property,
789 BindingFlags.Public | BindingFlags.Instance |
790 BindingFlags.IgnoreCase | BindingFlags.Static);
791 if (infos.Length != 0) {
792 // prefer public properties to public methods (it's what MS.NET does)
793 foreach (MemberInfo tmp in infos) {
794 if (tmp is PropertyInfo) {
803 } catch (Exception) {
807 ThrowParseException (
808 "Error parsing attribute '{0}': Type '{1}' does not have a public property named '{0}'",
809 memberName, inherits);
811 Type memberType = null;
812 if (mi is PropertyInfo) {
813 PropertyInfo pi = mi as PropertyInfo;
816 ThrowParseException (
817 "Error parsing attribute '{0}': The '{0}' property is read-only and cannot be set.",
819 memberType = pi.PropertyType;
820 } else if (mi is FieldInfo) {
821 memberType = ((FieldInfo)mi).FieldType;
823 ThrowParseException ("Could not determine member the kind of '{0}' in base type '{1}",
824 memberName, inherits);
825 TypeConverter converter = TypeDescriptor.GetConverter (memberType);
826 bool convertible = true;
829 if (converter == null || !converter.CanConvertFrom (typeof (string)))
834 value = converter.ConvertFromInvariantString (val);
835 } catch (Exception) {
841 ThrowParseException ("Error parsing attribute '{0}': Cannot create an object of type '{1}' from its string representation '{2}' for the '{3}' property.",
842 memberName, memberType, val, mi.Name);
844 UnknownAttributeDescriptor desc = new UnknownAttributeDescriptor (mi, value);
845 unknownMainAttributes.Add (desc);
848 internal void SetBaseType (string type)
851 if (type == null || type == DefaultBaseTypeName)
852 parent = DefaultBaseType;
856 if (parent == null) {
857 parent = LoadType (type);
860 ThrowParseException ("Cannot find type " + type);
862 if (!DefaultBaseType.IsAssignableFrom (parent))
863 ThrowParseException ("The parent type '" + type + "' does not derive from " + DefaultBaseType);
866 var pageParserFilter = PageParserFilter;
867 if (pageParserFilter != null && !pageParserFilter.AllowBaseType (parent))
868 throw new HttpException ("Base type '" + parent + "' is not allowed.");
873 internal void SetLanguage (string language)
875 this.language = language;
876 implicitLanguage = false;
879 internal void PushIncludeDir (string dir)
881 if (includeDirs == null)
882 includeDirs = new Stack <string> (1);
884 includeDirs.Push (dir);
887 internal string PopIncludeDir ()
889 if (includeDirs == null || includeDirs.Count == 0)
892 return includeDirs.Pop () as string;
895 Assembly GetAssemblyFromSource (string vpath)
897 vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
898 string realPath = MapPath (vpath, false);
899 if (!File.Exists (realPath))
900 ThrowParseException ("File " + vpath + " not found");
902 AddSourceDependency (vpath);
904 CompilerResults result;
906 CompilerParameters parameters;
907 CodeDomProvider provider = BaseCompiler.CreateProvider (HttpContext.Current, language, out parameters, out tmp);
908 if (provider == null)
909 throw new HttpException ("Cannot find provider for language '" + language + "'.");
911 AssemblyBuilder abuilder = new AssemblyBuilder (provider);
912 abuilder.CompilerOptions = parameters;
913 abuilder.AddAssemblyReference (BuildManager.GetReferencedAssemblies () as List <Assembly>);
914 abuilder.AddCodeFile (realPath);
915 result = abuilder.BuildAssembly (new VirtualPath (vpath));
917 if (result.NativeCompilerReturnValue != 0) {
918 using (StreamReader reader = new StreamReader (realPath)) {
919 throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
923 AddAssembly (result.CompiledAssembly, true);
924 return result.CompiledAssembly;
927 internal abstract string DefaultBaseTypeName { get; }
928 internal abstract string DefaultDirectiveName { get; }
930 internal bool LinePragmasOn {
931 get { return linePragmasOn; }
934 internal byte[] MD5Checksum {
935 get { return md5checksum; }
936 set { md5checksum = value; }
939 internal PageParserFilter PageParserFilter {
941 if (pageParserFilter != null)
942 return pageParserFilter;
944 Type t = PageParserFilterType;
948 pageParserFilter = Activator.CreateInstance (t) as PageParserFilter;
949 pageParserFilter.Initialize (this);
951 return pageParserFilter;
955 internal Type PageParserFilterType {
957 if (pageParserFilterType == null) {
958 pageParserFilterType = PageParser.DefaultPageParserFilterType;
959 if (pageParserFilterType != null)
960 return pageParserFilterType;
961 string typeName = PagesConfig.PageParserFilterType;
962 if (String.IsNullOrEmpty (typeName))
965 pageParserFilterType = HttpApplication.LoadType (typeName, true);
968 return pageParserFilterType;
972 Type DefaultBaseType {
974 Type type = Type.GetType (DefaultBaseTypeName, true);
980 internal ILocation DirectiveLocation {
981 get { return directiveLocation; }
984 internal string ParserDir {
986 if (includeDirs == null || includeDirs.Count == 0)
989 return includeDirs.Peek () as string;
993 internal string InputFile
995 get { return inputFile; }
996 set { inputFile = value; }
999 internal bool IsPartial {
1000 get { return (!srcIsLegacy && src != null); }
1003 internal string CodeBehindSource {
1012 internal string PartialClassName {
1013 get { return partialClassName; }
1016 internal string CodeFileBaseClass {
1017 get { return codeFileBaseClass; }
1020 internal string MetaResourceKey {
1021 get { return metaResourceKey; }
1024 internal Type CodeFileBaseClassType
1026 get { return codeFileBaseClassType; }
1029 internal List <UnknownAttributeDescriptor> UnknownMainAttributes
1031 get { return unknownMainAttributes; }
1034 internal string Text {
1035 get { return text; }
1036 set { text = value; }
1039 internal Type BaseType {
1041 if (baseType == null)
1042 SetBaseType (DefaultBaseTypeName);
1048 internal bool BaseTypeIsGlobal {
1049 get { return baseTypeIsGlobal; }
1050 set { baseTypeIsGlobal = value; }
1053 static long autoClassCounter = 0;
1055 internal string EncodeIdentifier (string value)
1057 if (value == null || value.Length == 0 || CodeGenerator.IsValidLanguageIndependentIdentifier (value))
1060 StringBuilder ret = new StringBuilder ();
1062 char ch = value [0];
1063 switch (Char.GetUnicodeCategory (ch)) {
1064 case UnicodeCategory.LetterNumber:
1065 case UnicodeCategory.LowercaseLetter:
1066 case UnicodeCategory.TitlecaseLetter:
1067 case UnicodeCategory.UppercaseLetter:
1068 case UnicodeCategory.OtherLetter:
1069 case UnicodeCategory.ModifierLetter:
1070 case UnicodeCategory.ConnectorPunctuation:
1074 case UnicodeCategory.DecimalDigitNumber:
1084 for (int i = 1; i < value.Length; i++) {
1086 switch (Char.GetUnicodeCategory (ch)) {
1087 case UnicodeCategory.LetterNumber:
1088 case UnicodeCategory.LowercaseLetter:
1089 case UnicodeCategory.TitlecaseLetter:
1090 case UnicodeCategory.UppercaseLetter:
1091 case UnicodeCategory.OtherLetter:
1092 case UnicodeCategory.ModifierLetter:
1093 case UnicodeCategory.ConnectorPunctuation:
1094 case UnicodeCategory.DecimalDigitNumber:
1095 case UnicodeCategory.NonSpacingMark:
1096 case UnicodeCategory.SpacingCombiningMark:
1097 case UnicodeCategory.Format:
1107 return ret.ToString ();
1110 internal string ClassName {
1112 if (className != null)
1115 string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
1118 if (String.IsNullOrEmpty (inputFile)) {
1120 using (StreamReader sr = Reader as StreamReader) {
1122 FileStream fr = sr.BaseStream as FileStream;
1130 if (String.IsNullOrEmpty (inFile)) {
1131 // generate a unique class name
1133 suffix = Interlocked.Increment (ref autoClassCounter);
1134 className = String.Format ("autoclass_nosource_{0:x}", suffix);
1138 if (StrUtils.StartsWith (inFile, physPath))
1139 className = inputFile.Substring (physPath.Length).ToLower (Helpers.InvariantCulture);
1141 className = Path.GetFileName (inputFile);
1142 className = EncodeIdentifier (className);
1147 internal List <ServerSideScript> Scripts {
1149 if (scripts == null)
1150 scripts = new List <ServerSideScript> ();
1156 internal Dictionary <string, bool> Imports {
1157 get { return imports; }
1160 internal List <string> Interfaces {
1161 get { return interfaces; }
1164 internal List <string> Assemblies {
1166 if (appAssemblyIndex != -1) {
1167 string o = assemblies [appAssemblyIndex];
1168 assemblies.RemoveAt (appAssemblyIndex);
1170 appAssemblyIndex = -1;
1177 internal RootBuilder RootBuilder {
1179 if (rootBuilder != null)
1181 AspGenerator generator = AspGenerator;
1182 if (generator != null)
1183 rootBuilder = generator.RootBuilder;
1187 set { rootBuilder = value; }
1190 internal List <string> Dependencies {
1191 get { return dependencies; }
1192 set { dependencies = value; }
1195 internal string CompilerOptions {
1196 get { return compilerOptions; }
1199 internal string Language {
1200 get { return language; }
1203 internal bool ImplicitLanguage {
1204 get { return implicitLanguage; }
1207 internal bool StrictOn {
1208 get { return strictOn; }
1211 internal bool ExplicitOn {
1212 get { return explicitOn; }
1215 internal bool Debug {
1216 get { return debug; }
1219 internal bool OutputCache {
1220 get { return output_cache; }
1223 internal int OutputCacheDuration {
1224 get { return oc_duration; }
1227 internal OutputCacheParsedParams OutputCacheParsedParameters {
1228 get { return oc_parsed_params; }
1231 internal string OutputCacheSqlDependency {
1232 get { return oc_sqldependency; }
1235 internal string OutputCacheCacheProfile {
1236 get { return oc_cacheprofile; }
1239 internal string OutputCacheVaryByContentEncodings {
1240 get { return oc_content_encodings; }
1243 internal bool OutputCacheNoStore {
1244 get { return oc_nostore; }
1247 internal virtual TextReader Reader {
1248 get { return null; }
1252 internal string OutputCacheVaryByHeader {
1253 get { return oc_header; }
1256 internal string OutputCacheVaryByCustom {
1257 get { return oc_custom; }
1260 internal string OutputCacheVaryByControls {
1261 get { return oc_controls; }
1264 internal bool OutputCacheShared {
1265 get { return oc_shared; }
1268 internal OutputCacheLocation OutputCacheLocation {
1269 get { return oc_location; }
1272 internal string OutputCacheVaryByParam {
1273 get { return oc_param; }
1276 internal List <string> RegisteredTagNames {
1277 get { return registeredTagNames; }
1280 internal PagesSection PagesConfig {
1281 get { return GetConfigSection <PagesSection> ("system.web/pages") as PagesSection; }
1284 internal AspGenerator AspGenerator {