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.ComponentModel;
35 using System.Globalization;
37 using System.Reflection;
38 using System.Security.Permissions;
40 using System.Threading;
41 using System.Web.Compilation;
42 using System.Web.Configuration;
43 using System.Web.Hosting;
44 using System.Web.Util;
47 using System.Collections.Generic;
50 namespace System.Web.UI {
51 internal class ServerSideScript
53 public readonly string Script;
54 public readonly ILocation Location;
56 public ServerSideScript (string script, ILocation location)
64 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
65 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
66 public abstract class TemplateParser : BaseParser
70 internal enum OutputCacheParsedParams
73 CacheProfile = 0x0002,
75 SqlDependency = 0x0008,
76 VaryByCustom = 0x0010,
77 VaryByHeader = 0x0020,
78 VaryByControl = 0x0040,
79 VaryByContentEncodings = 0x0080
85 Hashtable mainAttributes;
86 ArrayList dependencies;
90 string[] binDirAssemblies;
91 Dictionary <string, bool> namespacesCache;
92 List <string> imports;
93 List <string> interfaces;
94 List <ServerSideScript> scripts;
101 bool baseTypeIsGlobal = true;
103 RootBuilder rootBuilder;
105 string compilerOptions;
107 bool implicitLanguage;
110 bool linePragmasOn = true;
113 string oc_header, oc_custom, oc_param, oc_controls;
115 string oc_content_encodings, oc_cacheprofile, oc_sqldependency;
117 OutputCacheParsedParams oc_parsed_params = 0;
120 OutputCacheLocation oc_location;
122 // Kludge needed to support pre-parsing of the main directive (see
123 // AspNetGenerator.GetRootBuilderType)
124 internal int allowedMainDirectives = 0;
129 string partialClassName;
130 string codeFileBaseClass;
131 string metaResourceKey;
132 Type codeFileBaseClassType;
133 Type pageParserFilterType;
134 PageParserFilter pageParserFilter;
136 List <UnknownAttributeDescriptor> unknownMainAttributes;
137 Stack <string> includeDirs;
138 List <string> registeredTagNames;
141 Assembly srcAssembly;
143 ILocation directiveLocation;
145 int appAssemblyIndex = -1;
147 internal TemplateParser ()
149 LoadConfigDefaults ();
151 imports = new List <string> ();
152 AddNamespaces (imports);
154 imports = new ArrayList ();
155 imports.Add ("System");
156 imports.Add ("System.Collections");
157 imports.Add ("System.Collections.Specialized");
158 imports.Add ("System.Configuration");
159 imports.Add ("System.Text");
160 imports.Add ("System.Text.RegularExpressions");
161 imports.Add ("System.Web");
162 imports.Add ("System.Web.Caching");
163 imports.Add ("System.Web.Security");
164 imports.Add ("System.Web.SessionState");
165 imports.Add ("System.Web.UI");
166 imports.Add ("System.Web.UI.WebControls");
167 imports.Add ("System.Web.UI.HtmlControls");
170 assemblies = new ArrayList ();
172 CompilationSection compConfig = CompilationConfig;
173 foreach (AssemblyInfo info in compConfig.Assemblies) {
174 if (info.Assembly != "*")
175 AddAssemblyByName (info.Assembly);
178 foreach (NamespaceInfo info in PagesConfig.Namespaces) {
179 imports.Add (info.Namespace);
182 CompilationConfiguration compConfig = CompilationConfig;
184 foreach (string a in compConfig.Assemblies)
185 AddAssemblyByName (a);
186 if (compConfig.AssembliesInBin)
187 AddAssembliesInBin ();
190 language = compConfig.DefaultLanguage;
191 implicitLanguage = true;
194 internal virtual void LoadConfigDefaults ()
196 debug = CompilationConfig.Debug;
199 internal void AddApplicationAssembly ()
201 if (Context.ApplicationInstance == null)
202 return; // this may happen if we have Global.asax and have
203 // controls registered from Web.Config
204 string location = Context.ApplicationInstance.AssemblyLocation;
205 if (location != typeof (TemplateParser).Assembly.Location) {
206 appAssemblyIndex = assemblies.Add (location);
210 protected abstract Type CompileIntoType ();
213 internal void AddControl (Type type, IDictionary attributes)
215 AspGenerator generator = AspGenerator;
216 if (generator == null)
218 generator.AddControl (type, attributes);
221 void AddNamespaces (List <string> imports)
223 if (BuildManager.HaveResources)
224 imports.Add ("System.Resources");
226 PagesSection pages = PagesConfig;
230 NamespaceCollection namespaces = pages.Namespaces;
231 if (namespaces == null || namespaces.Count == 0)
234 foreach (NamespaceInfo nsi in namespaces)
235 imports.Add (nsi.Namespace);
239 internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
241 string realpath = null;
242 bool fileExists = false;
245 VirtualFile vf = null;
246 VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
247 VirtualPath vp = new VirtualPath (src, BaseVirtualDir);
248 string vpAbsolute = vp.Absolute;
250 if (vpp.FileExists (vpAbsolute)) {
252 vf = vpp.GetFile (vpAbsolute);
254 realpath = MapPath (vf.VirtualPath);
257 realpath = MapPath (src);
258 fileExists = File.Exists (realpath);
261 ThrowParseFileNotFound (src);
263 if (String.Compare (realpath, inputFile, false, Helpers.InvariantCulture) == 0)
267 string vpath = vf.VirtualPath;
269 string vpath = VirtualPathUtility.Combine (BaseVirtualDir, src);
270 if (VirtualPathUtility.IsAbsolute (vpath))
271 vpath = VirtualPathUtility.ToAppRelative (vpath);
276 RegisterTagName (tagPrefix + ":" + tagName);
277 RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, vpath);
280 ArrayList other_deps = new ArrayList ();
281 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
282 foreach (string s in other_deps)
284 AddAssembly (type.Assembly, true);
285 RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, type);
287 AddDependency (vpath);
288 } catch (ParseException pe) {
289 if (this is UserControlParser)
290 throw new ParseException (Location, pe.Message, pe);
295 internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
300 if (assembly != null && assembly.Length > 0)
301 ass = AddAssemblyByName (assembly);
303 RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
306 internal virtual void HandleOptions (object obj)
310 internal static string GetOneKey (Hashtable tbl)
312 foreach (object key in tbl.Keys)
313 return key.ToString ();
318 internal virtual void AddDirective (string directive, Hashtable atts)
321 var pageParserFilter = PageParserFilter;
323 if (String.Compare (directive, DefaultDirectiveName, true, Helpers.InvariantCulture) == 0) {
325 bool allowMainDirective = allowedMainDirectives > 0;
327 bool allowMainDirective = false;
329 if (mainAttributes != null && !allowMainDirective)
330 ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
332 allowedMainDirectives--;
333 if (mainAttributes != null)
336 if (pageParserFilter != null)
337 pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
340 mainAttributes = atts;
341 ProcessMainAttributes (mainAttributes);
345 else if (pageParserFilter != null)
346 pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
349 int cmp = String.Compare ("Assembly", directive, true, Helpers.InvariantCulture);
351 string name = GetString (atts, "Name", null);
352 string src = GetString (atts, "Src", null);
355 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
357 if (name == null && src == null)
358 ThrowParseException ("You gotta specify Src or Name");
360 if (name != null && src != null)
361 ThrowParseException ("Src and Name cannot be used together");
364 AddAssemblyByName (name);
366 GetAssemblyFromSource (src);
372 cmp = String.Compare ("Import", directive, true, Helpers.InvariantCulture);
374 string namesp = GetString (atts, "Namespace", null);
376 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
382 cmp = String.Compare ("Implements", directive, true, Helpers.InvariantCulture);
384 string ifacename = GetString (atts, "Interface", "");
387 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
389 Type iface = LoadType (ifacename);
391 ThrowParseException ("Cannot find type " + ifacename);
393 if (!iface.IsInterface)
394 ThrowParseException (iface + " is not an interface");
396 AddInterface (iface.FullName);
400 cmp = String.Compare ("OutputCache", directive, true, Helpers.InvariantCulture);
402 HttpResponse response = HttpContext.Current.Response;
403 if (response != null)
404 response.Cache.SetValidUntilExpires (true);
408 if (atts ["Duration"] == null)
409 ThrowParseException ("The directive is missing a 'duration' attribute.");
410 if (atts ["VaryByParam"] == null && atts ["VaryByControl"] == null)
411 ThrowParseException ("This directive is missing 'VaryByParam' " +
412 "or 'VaryByControl' attribute, which should be set to \"none\", \"*\", " +
413 "or a list of name/value pairs.");
415 foreach (DictionaryEntry entry in atts) {
416 string key = (string) entry.Key;
420 switch (key.ToLower (Helpers.InvariantCulture)) {
422 oc_duration = Int32.Parse ((string) entry.Value);
424 ThrowParseException ("The 'duration' attribute must be set " +
425 "to a positive integer value");
428 case "sqldependency":
429 oc_sqldependency = (string) entry.Value;
434 oc_nostore = Boolean.Parse ((string) entry.Value);
435 oc_parsed_params |= OutputCacheParsedParams.NoStore;
437 ThrowParseException ("The 'NoStore' attribute is case sensitive" +
438 " and must be set to 'true' or 'false'.");
443 oc_cacheprofile = (string) entry.Value;
444 oc_parsed_params |= OutputCacheParsedParams.CacheProfile;
447 case "varybycontentencodings":
448 oc_content_encodings = (string) entry.Value;
449 oc_parsed_params |= OutputCacheParsedParams.VaryByContentEncodings;
453 oc_param = (string) entry.Value;
454 if (String.Compare (oc_param, "none", true, Helpers.InvariantCulture) == 0)
458 oc_header = (string) entry.Value;
460 oc_parsed_params |= OutputCacheParsedParams.VaryByHeader;
464 oc_custom = (string) entry.Value;
466 oc_parsed_params |= OutputCacheParsedParams.VaryByCustom;
470 if (!(this is PageParser))
474 oc_location = (OutputCacheLocation) Enum.Parse (
475 typeof (OutputCacheLocation), (string) entry.Value, true);
477 oc_parsed_params |= OutputCacheParsedParams.Location;
480 ThrowParseException ("The 'location' attribute is case sensitive and " +
481 "must be one of the following values: Any, Client, " +
482 "Downstream, Server, None, ServerAndClient.");
485 case "varybycontrol":
487 if (this is PageParser)
490 oc_controls = (string) entry.Value;
492 oc_parsed_params |= OutputCacheParsedParams.VaryByControl;
496 if (this is PageParser)
500 oc_shared = Boolean.Parse ((string) entry.Value);
502 ThrowParseException ("The 'shared' attribute is case sensitive" +
503 " and must be set to 'true' or 'false'.");
507 ThrowParseException ("The '" + key + "' attribute is not " +
508 "supported by the 'Outputcache' directive.");
517 ThrowParseException ("Unknown directive: " + directive);
520 internal Type LoadType (string typeName)
522 Type type = HttpApplication.LoadType (typeName);
525 Assembly asm = type.Assembly;
526 string location = asm.Location;
528 string dirname = Path.GetDirectoryName (location);
529 bool doAddAssembly = true;
530 if (dirname == HttpApplication.BinDirectory)
531 doAddAssembly = false;
534 AddAssembly (asm, true);
540 void AddAssembliesInBin ()
543 foreach (string s in HttpApplication.BinDirectoryAssemblies) {
545 asm = Assembly.LoadFrom (s);
546 assemblies.Add (asm.Location);
547 } catch (BadImageFormatException) {
554 internal virtual void AddInterface (string iface)
556 if (interfaces == null) {
558 interfaces = new List <string> ();
560 interfaces = new ArrayList ();
564 if (!interfaces.Contains (iface))
565 interfaces.Add (iface);
568 internal virtual void AddImport (string namesp)
570 if (namesp == null || namesp.Length == 0)
573 if (imports == null) {
575 imports = new List <string> ();
577 imports = new ArrayList ();
581 if (imports.Contains (namesp))
584 imports.Add (namesp);
586 AddAssemblyForNamespace (namesp);
591 void AddAssemblyForNamespace (string namesp)
593 if (binDirAssemblies == null)
594 binDirAssemblies = HttpApplication.BinDirectoryAssemblies;
595 if (binDirAssemblies.Length == 0)
598 if (namespacesCache == null)
599 namespacesCache = new Dictionary <string, bool> ();
600 else if (namespacesCache.ContainsKey (namesp))
603 foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
604 if (FindNamespaceInAssembly (asm, namesp))
607 IList tla = BuildManager.TopLevelAssemblies;
608 if (tla != null && tla.Count > 0) {
609 foreach (Assembly asm in tla) {
610 if (FindNamespaceInAssembly (asm, namesp))
616 foreach (string s in binDirAssemblies) {
617 a = Assembly.LoadFrom (s);
618 if (FindNamespaceInAssembly (a, namesp))
623 bool FindNamespaceInAssembly (Assembly asm, string namesp)
628 asmTypes = asm.GetTypes ();
629 } catch (ReflectionTypeLoadException) {
634 foreach (Type type in asmTypes) {
635 if (String.Compare (type.Namespace, namesp, StringComparison.Ordinal) == 0) {
636 namespacesCache.Add (namesp, true);
637 AddAssembly (asm, true);
646 internal virtual void AddSourceDependency (string filename)
648 if (dependencies != null && dependencies.Contains (filename))
649 ThrowParseException ("Circular file references are not allowed. File: " + filename);
651 AddDependency (filename);
654 internal virtual void AddDependency (string filename)
656 if (filename == null || filename == String.Empty)
659 if (dependencies == null)
660 dependencies = new ArrayList ();
662 if (!dependencies.Contains (filename))
663 dependencies.Add (filename);
666 internal virtual void AddAssembly (Assembly assembly, bool fullPath)
668 if (assembly == null || assembly.Location == String.Empty)
672 anames = new Hashtable ();
674 string name = assembly.GetName ().Name;
675 string loc = assembly.Location;
677 if (!assemblies.Contains (loc)) {
678 assemblies.Add (loc);
682 anames [loc] = assembly;
684 if (!assemblies.Contains (name)) {
685 assemblies.Add (name);
688 anames [name] = assembly;
692 internal virtual Assembly AddAssemblyByFileName (string filename)
694 Assembly assembly = null;
695 Exception error = null;
698 assembly = Assembly.LoadFrom (filename);
699 } catch (Exception e) { error = e; }
701 if (assembly == null)
702 ThrowParseException ("Assembly " + filename + " not found", error);
704 AddAssembly (assembly, true);
708 internal virtual Assembly AddAssemblyByName (string name)
711 anames = new Hashtable ();
713 if (anames.Contains (name)) {
714 object o = anames [name];
721 Assembly assembly = null;
722 Exception error = null;
724 assembly = Assembly.Load (name);
725 } catch (Exception e) { error = e; }
727 if (assembly == null) {
729 assembly = Assembly.LoadWithPartialName (name);
730 } catch (Exception e) { error = e; }
733 if (assembly == null)
734 ThrowParseException ("Assembly " + name + " not found", error);
736 AddAssembly (assembly, true);
740 internal virtual void ProcessMainAttributes (Hashtable atts)
742 directiveLocation = new System.Web.Compilation.Location (Location);
745 CompilationSection compConfig;
747 CompilationConfiguration compConfig;
750 compConfig = CompilationConfig;
752 atts.Remove ("Description"); // ignored
754 atts.Remove ("CodeBehind"); // ignored
756 atts.Remove ("AspCompat"); // ignored
758 debug = GetBool (atts, "Debug", compConfig.Debug);
759 compilerOptions = GetString (atts, "CompilerOptions", "");
760 language = GetString (atts, "Language", "");
761 if (language.Length != 0)
762 implicitLanguage = false;
764 language = compConfig.DefaultLanguage;
766 strictOn = GetBool (atts, "Strict", compConfig.Strict);
767 explicitOn = GetBool (atts, "Explicit", compConfig.Explicit);
768 if (atts.ContainsKey ("LinePragmas"))
769 linePragmasOn = GetBool (atts, "LinePragmas", true);
771 string inherits = GetString (atts, "Inherits", null);
773 string srcRealPath = null;
775 // In ASP 2, the source file is actually integrated with
776 // the generated file via the use of partial classes. This
777 // means that the code file has to be confirmed, but not
778 // used at this point.
779 src = GetString (atts, "CodeFile", null);
780 codeFileBaseClass = GetString (atts, "CodeFileBaseClass", null);
782 if (src == null && codeFileBaseClass != null)
783 ThrowParseException ("The 'CodeFileBaseClass' attribute cannot be used without a 'CodeFile' attribute");
785 string legacySrc = GetString (atts, "Src", null);
786 if (legacySrc != null) {
787 legacySrc = UrlUtils.Combine (BaseVirtualDir, legacySrc);
788 GetAssemblyFromSource (legacySrc);
792 legacySrc = MapPath (legacySrc, false);
793 srcRealPath = legacySrc;
794 if (!File.Exists (srcRealPath))
795 ThrowParseException ("File " + src + " not found");
799 legacySrc = MapPath (legacySrc, false);
801 AddDependency (legacySrc);
804 if (!srcIsLegacy && src != null && inherits != null) {
805 // Make sure the source exists
806 src = UrlUtils.Combine (BaseVirtualDir, src);
807 srcRealPath = MapPath (src, false);
809 if (!HostingEnvironment.VirtualPathProvider.FileExists (src))
810 ThrowParseException ("File " + src + " not found");
812 // We are going to create a partial class that shares
813 // the same name as the inherits tag, so reset the
814 // name. The base type is changed because it is the
815 // code file's responsibilty to extend the classes
817 partialClassName = inherits;
819 // Add the code file as an option to the
820 // compiler. This lets both files be compiled at once.
821 compilerOptions += " \"" + srcRealPath + "\"";
823 if (codeFileBaseClass != null) {
825 codeFileBaseClassType = LoadType (codeFileBaseClass);
826 } catch (Exception) {
829 if (codeFileBaseClassType == null)
830 ThrowParseException ("Could not load type '{0}'", codeFileBaseClass);
832 } else if (inherits != null) {
833 // We just set the inherits directly because this is a
834 // Single-Page model.
835 SetBaseType (inherits);
838 string src = GetString (atts, "Src", null);
841 srcAssembly = GetAssemblyFromSource (src);
843 if (inherits != null)
844 SetBaseType (inherits);
847 if (VirtualPathUtility.IsAbsolute (src))
848 src = VirtualPathUtility.ToAppRelative (src);
852 className = GetString (atts, "ClassName", null);
853 if (className != null) {
855 string [] identifiers = className.Split ('.');
856 for (int i = 0; i < identifiers.Length; i++)
857 if (!CodeGenerator.IsValidLanguageIndependentIdentifier (identifiers [i]))
858 ThrowParseException (String.Format ("'{0}' is not a valid "
859 + "value for attribute 'classname'.", className));
861 if (!CodeGenerator.IsValidLanguageIndependentIdentifier (className))
862 ThrowParseException (String.Format ("'{0}' is not a valid "
863 + "value for attribute 'classname'.", className));
868 if (this is TemplateControlParser)
869 metaResourceKey = GetString (atts, "meta:resourcekey", null);
871 if (inherits != null && (this is PageParser || this is UserControlParser) && atts.Count > 0) {
872 if (unknownMainAttributes == null)
873 unknownMainAttributes = new List <UnknownAttributeDescriptor> ();
876 foreach (DictionaryEntry de in atts) {
877 key = de.Key as string;
878 val = de.Value as string;
880 if (String.IsNullOrEmpty (key) || String.IsNullOrEmpty (val))
882 CheckUnknownAttribute (key, val, inherits);
888 ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
892 void RegisterTagName (string tagName)
894 if (registeredTagNames == null)
895 registeredTagNames = new List <string> ();
897 if (registeredTagNames.Contains (tagName))
900 registeredTagNames.Add (tagName);
903 void CheckUnknownAttribute (string name, string val, string inherits)
905 MemberInfo mi = null;
906 bool missing = false;
907 string memberName = name.Trim ().ToLower (Helpers.InvariantCulture);
908 Type parent = codeFileBaseClassType;
914 MemberInfo[] infos = parent.GetMember (memberName,
915 MemberTypes.Field | MemberTypes.Property,
916 BindingFlags.Public | BindingFlags.Instance |
917 BindingFlags.IgnoreCase | BindingFlags.Static);
918 if (infos.Length != 0) {
919 // prefer public properties to public methods (it's what MS.NET does)
920 foreach (MemberInfo tmp in infos) {
921 if (tmp is PropertyInfo) {
930 } catch (Exception) {
934 ThrowParseException (
935 "Error parsing attribute '{0}': Type '{1}' does not have a public property named '{0}'",
936 memberName, inherits);
938 Type memberType = null;
939 if (mi is PropertyInfo) {
940 PropertyInfo pi = mi as PropertyInfo;
943 ThrowParseException (
944 "Error parsing attribute '{0}': The '{0}' property is read-only and cannot be set.",
946 memberType = pi.PropertyType;
947 } else if (mi is FieldInfo) {
948 memberType = ((FieldInfo)mi).FieldType;
950 ThrowParseException ("Could not determine member the kind of '{0}' in base type '{1}",
951 memberName, inherits);
952 TypeConverter converter = TypeDescriptor.GetConverter (memberType);
953 bool convertible = true;
956 if (converter == null || !converter.CanConvertFrom (typeof (string)))
961 value = converter.ConvertFromInvariantString (val);
962 } catch (Exception) {
968 ThrowParseException ("Error parsing attribute '{0}': Cannot create an object of type '{1}' from its string representation '{2}' for the '{3}' property.",
969 memberName, memberType, val, mi.Name);
971 UnknownAttributeDescriptor desc = new UnknownAttributeDescriptor (mi, value);
972 unknownMainAttributes.Add (desc);
976 internal void SetBaseType (string type)
979 if (type == null || type == DefaultBaseTypeName)
980 parent = DefaultBaseType;
984 if (parent == null) {
986 parent = LoadType (type);
989 if (srcAssembly != null)
990 parent = srcAssembly.GetType (type);
993 parent = LoadType (type);
997 ThrowParseException ("Cannot find type " + type);
999 if (!DefaultBaseType.IsAssignableFrom (parent))
1000 ThrowParseException ("The parent type '" + type + "' does not derive from " + DefaultBaseType);
1004 var pageParserFilter = PageParserFilter;
1005 if (pageParserFilter != null && !pageParserFilter.AllowBaseType (parent))
1006 throw new HttpException ("Base type '" + parent + "' is not allowed.");
1012 internal void SetLanguage (string language)
1014 this.language = language;
1015 implicitLanguage = false;
1018 internal void PushIncludeDir (string dir)
1020 if (includeDirs == null) {
1022 includeDirs = new Stack <string> (1);
1024 includeDirs = new Stack (1);
1028 includeDirs.Push (dir);
1031 internal string PopIncludeDir ()
1033 if (includeDirs == null || includeDirs.Count == 0)
1036 return includeDirs.Pop () as string;
1039 Assembly GetAssemblyFromSource (string vpath)
1041 vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
1042 string realPath = MapPath (vpath, false);
1043 if (!File.Exists (realPath))
1044 ThrowParseException ("File " + vpath + " not found");
1046 AddSourceDependency (vpath);
1048 CompilerResults result;
1052 CompilerParameters parameters;
1053 CodeDomProvider provider = BaseCompiler.CreateProvider (HttpContext.Current, language, out parameters, out tmp);
1054 if (provider == null)
1055 throw new HttpException ("Cannot find provider for language '" + language + "'.");
1057 AssemblyBuilder abuilder = new AssemblyBuilder (provider);
1058 abuilder.CompilerOptions = parameters;
1059 abuilder.AddAssemblyReference (BuildManager.GetReferencedAssemblies () as List <Assembly>);
1060 abuilder.AddCodeFile (realPath);
1061 result = abuilder.BuildAssembly (new VirtualPath (vpath));
1063 result = CachingCompiler.Compile (language, realPath, realPath, assemblies, Debug);
1065 if (result.NativeCompilerReturnValue != 0) {
1066 using (StreamReader reader = new StreamReader (realPath)) {
1067 throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
1071 AddAssembly (result.CompiledAssembly, true);
1072 return result.CompiledAssembly;
1075 internal abstract string DefaultBaseTypeName { get; }
1076 internal abstract string DefaultDirectiveName { get; }
1078 internal bool LinePragmasOn {
1079 get { return linePragmasOn; }
1083 internal byte[] MD5Checksum {
1084 get { return md5checksum; }
1085 set { md5checksum = value; }
1088 internal PageParserFilter PageParserFilter {
1090 if (pageParserFilter != null)
1091 return pageParserFilter;
1093 Type t = PageParserFilterType;
1097 pageParserFilter = Activator.CreateInstance (t) as PageParserFilter;
1098 pageParserFilter.Initialize (this);
1100 return pageParserFilter;
1104 internal Type PageParserFilterType {
1106 if (pageParserFilterType == null) {
1107 string typeName = PagesConfig.PageParserFilterType;
1108 if (String.IsNullOrEmpty (typeName))
1111 pageParserFilterType = HttpApplication.LoadType (typeName, true);
1114 return pageParserFilterType;
1119 internal Type DefaultBaseType {
1121 Type type = Type.GetType (DefaultBaseTypeName, true);
1127 internal ILocation DirectiveLocation {
1128 get { return directiveLocation; }
1131 internal string ParserDir {
1133 if (includeDirs == null || includeDirs.Count == 0)
1136 return includeDirs.Peek () as string;
1140 internal string InputFile
1142 get { return inputFile; }
1143 set { inputFile = value; }
1147 internal bool IsPartial {
1148 get { return (!srcIsLegacy && src != null); }
1151 internal string CodeBehindSource {
1160 internal string PartialClassName {
1161 get { return partialClassName; }
1164 internal string CodeFileBaseClass {
1165 get { return codeFileBaseClass; }
1168 internal string MetaResourceKey {
1169 get { return metaResourceKey; }
1172 internal Type CodeFileBaseClassType
1174 get { return codeFileBaseClassType; }
1177 internal List <UnknownAttributeDescriptor> UnknownMainAttributes
1179 get { return unknownMainAttributes; }
1183 internal string Text {
1184 get { return text; }
1185 set { text = value; }
1188 internal Type BaseType {
1190 if (baseType == null)
1191 SetBaseType (DefaultBaseTypeName);
1197 internal bool BaseTypeIsGlobal {
1198 get { return baseTypeIsGlobal; }
1199 set { baseTypeIsGlobal = value; }
1203 static long autoClassCounter = 0;
1206 internal string EncodeIdentifier (string value)
1208 if (value == null || value.Length == 0 || CodeGenerator.IsValidLanguageIndependentIdentifier (value))
1211 StringBuilder ret = new StringBuilder ();
1213 char ch = value [0];
1214 switch (Char.GetUnicodeCategory (ch)) {
1215 case UnicodeCategory.LetterNumber:
1216 case UnicodeCategory.LowercaseLetter:
1217 case UnicodeCategory.TitlecaseLetter:
1218 case UnicodeCategory.UppercaseLetter:
1219 case UnicodeCategory.OtherLetter:
1220 case UnicodeCategory.ModifierLetter:
1221 case UnicodeCategory.ConnectorPunctuation:
1225 case UnicodeCategory.DecimalDigitNumber:
1235 for (int i = 1; i < value.Length; i++) {
1237 switch (Char.GetUnicodeCategory (ch)) {
1238 case UnicodeCategory.LetterNumber:
1239 case UnicodeCategory.LowercaseLetter:
1240 case UnicodeCategory.TitlecaseLetter:
1241 case UnicodeCategory.UppercaseLetter:
1242 case UnicodeCategory.OtherLetter:
1243 case UnicodeCategory.ModifierLetter:
1244 case UnicodeCategory.ConnectorPunctuation:
1245 case UnicodeCategory.DecimalDigitNumber:
1246 case UnicodeCategory.NonSpacingMark:
1247 case UnicodeCategory.SpacingCombiningMark:
1248 case UnicodeCategory.Format:
1258 return ret.ToString ();
1261 internal string ClassName {
1263 if (className != null)
1267 string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
1270 if (String.IsNullOrEmpty (inputFile)) {
1272 using (StreamReader sr = Reader as StreamReader) {
1274 FileStream fr = sr.BaseStream as FileStream;
1282 if (String.IsNullOrEmpty (inFile)) {
1283 // generate a unique class name
1285 suffix = Interlocked.Increment (ref autoClassCounter);
1286 className = String.Format ("autoclass_nosource_{0:x}", suffix);
1290 if (StrUtils.StartsWith (inFile, physPath))
1291 className = inputFile.Substring (physPath.Length).ToLower (Helpers.InvariantCulture);
1294 className = Path.GetFileName (inputFile);
1295 className = EncodeIdentifier (className);
1301 internal List <ServerSideScript> Scripts {
1303 if (scripts == null)
1304 scripts = new List <ServerSideScript> ();
1310 internal List <string> Imports {
1311 get { return imports; }
1314 internal List <string> Interfaces {
1315 get { return interfaces; }
1318 internal ArrayList Scripts {
1320 if (scripts == null)
1321 scripts = new ArrayList ();
1327 internal ArrayList Imports {
1328 get { return imports; }
1331 internal ArrayList Interfaces {
1332 get { return interfaces; }
1336 internal ArrayList Assemblies {
1338 if (appAssemblyIndex != -1) {
1339 object o = assemblies [appAssemblyIndex];
1340 assemblies.RemoveAt (appAssemblyIndex);
1342 appAssemblyIndex = -1;
1349 internal RootBuilder RootBuilder {
1352 if (rootBuilder != null)
1354 AspGenerator generator = AspGenerator;
1355 if (generator != null)
1356 rootBuilder = generator.RootBuilder;
1360 set { rootBuilder = value; }
1363 internal ArrayList Dependencies {
1364 get { return dependencies; }
1365 set { dependencies = value; }
1368 internal string CompilerOptions {
1369 get { return compilerOptions; }
1372 internal string Language {
1373 get { return language; }
1376 internal bool ImplicitLanguage {
1377 get { return implicitLanguage; }
1380 internal bool StrictOn {
1381 get { return strictOn; }
1384 internal bool ExplicitOn {
1385 get { return explicitOn; }
1388 internal bool Debug {
1389 get { return debug; }
1392 internal bool OutputCache {
1393 get { return output_cache; }
1396 internal int OutputCacheDuration {
1397 get { return oc_duration; }
1401 internal OutputCacheParsedParams OutputCacheParsedParameters {
1402 get { return oc_parsed_params; }
1405 internal string OutputCacheSqlDependency {
1406 get { return oc_sqldependency; }
1409 internal string OutputCacheCacheProfile {
1410 get { return oc_cacheprofile; }
1413 internal string OutputCacheVaryByContentEncodings {
1414 get { return oc_content_encodings; }
1417 internal bool OutputCacheNoStore {
1418 get { return oc_nostore; }
1421 internal virtual TextReader Reader {
1422 get { return null; }
1427 internal string OutputCacheVaryByHeader {
1428 get { return oc_header; }
1431 internal string OutputCacheVaryByCustom {
1432 get { return oc_custom; }
1435 internal string OutputCacheVaryByControls {
1436 get { return oc_controls; }
1439 internal bool OutputCacheShared {
1440 get { return oc_shared; }
1443 internal OutputCacheLocation OutputCacheLocation {
1444 get { return oc_location; }
1447 internal string OutputCacheVaryByParam {
1448 get { return oc_param; }
1452 internal List <string> RegisteredTagNames {
1453 get { return registeredTagNames; }
1456 internal PagesSection PagesConfig {
1457 get { return GetConfigSection <PagesSection> ("system.web/pages") as PagesSection; }
1460 internal AspGenerator AspGenerator {
1465 internal PagesConfiguration PagesConfig {
1466 get { return PagesConfiguration.GetInstance (Context); }