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;
121 CultureInfo invariantCulture = CultureInfo.InvariantCulture;
123 // Kludge needed to support pre-parsing of the main directive (see
124 // AspNetGenerator.GetRootBuilderType)
125 internal int allowedMainDirectives = 0;
130 string partialClassName;
131 string codeFileBaseClass;
132 string metaResourceKey;
133 Type codeFileBaseClassType;
134 Type pageParserFilterType;
135 PageParserFilter pageParserFilter;
137 List <UnknownAttributeDescriptor> unknownMainAttributes;
138 Stack <string> includeDirs;
139 List <string> registeredTagNames;
142 Assembly srcAssembly;
144 ILocation directiveLocation;
146 int appAssemblyIndex = -1;
148 internal TemplateParser ()
150 LoadConfigDefaults ();
152 imports = new List <string> ();
153 AddNamespaces (imports);
155 imports = new ArrayList ();
156 imports.Add ("System");
157 imports.Add ("System.Collections");
158 imports.Add ("System.Collections.Specialized");
159 imports.Add ("System.Configuration");
160 imports.Add ("System.Text");
161 imports.Add ("System.Text.RegularExpressions");
162 imports.Add ("System.Web");
163 imports.Add ("System.Web.Caching");
164 imports.Add ("System.Web.Security");
165 imports.Add ("System.Web.SessionState");
166 imports.Add ("System.Web.UI");
167 imports.Add ("System.Web.UI.WebControls");
168 imports.Add ("System.Web.UI.HtmlControls");
171 assemblies = new ArrayList ();
173 CompilationSection compConfig = CompilationConfig;
174 foreach (AssemblyInfo info in compConfig.Assemblies) {
175 if (info.Assembly != "*")
176 AddAssemblyByName (info.Assembly);
179 foreach (NamespaceInfo info in PagesConfig.Namespaces) {
180 imports.Add (info.Namespace);
183 CompilationConfiguration compConfig = CompilationConfig;
185 foreach (string a in compConfig.Assemblies)
186 AddAssemblyByName (a);
187 if (compConfig.AssembliesInBin)
188 AddAssembliesInBin ();
191 language = compConfig.DefaultLanguage;
192 implicitLanguage = true;
195 internal virtual void LoadConfigDefaults ()
197 debug = CompilationConfig.Debug;
200 internal void AddApplicationAssembly ()
202 if (Context.ApplicationInstance == null)
203 return; // this may happen if we have Global.asax and have
204 // controls registered from Web.Config
205 string location = Context.ApplicationInstance.AssemblyLocation;
206 if (location != typeof (TemplateParser).Assembly.Location) {
207 appAssemblyIndex = assemblies.Add (location);
211 protected abstract Type CompileIntoType ();
214 internal void AddControl (Type type, IDictionary attributes)
216 AspGenerator generator = AspGenerator;
217 if (generator == null)
219 generator.AddControl (type, attributes);
222 void AddNamespaces (List <string> imports)
224 if (BuildManager.HaveResources)
225 imports.Add ("System.Resources");
227 PagesSection pages = PagesConfig;
231 NamespaceCollection namespaces = pages.Namespaces;
232 if (namespaces == null || namespaces.Count == 0)
235 foreach (NamespaceInfo nsi in namespaces)
236 imports.Add (nsi.Namespace);
240 internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
242 string realpath = null;
243 bool fileExists = false;
246 VirtualFile vf = null;
247 VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
248 VirtualPath vp = new VirtualPath (src, BaseVirtualDir);
249 string vpAbsolute = vp.Absolute;
251 if (vpp.FileExists (vpAbsolute)) {
253 vf = vpp.GetFile (vpAbsolute);
255 realpath = MapPath (vf.VirtualPath);
258 realpath = MapPath (src);
259 fileExists = File.Exists (realpath);
262 ThrowParseFileNotFound (src);
264 if (String.Compare (realpath, inputFile, false, invariantCulture) == 0)
268 string vpath = vf.VirtualPath;
270 string vpath = VirtualPathUtility.Combine (BaseVirtualDir, src);
271 if (VirtualPathUtility.IsAbsolute (vpath))
272 vpath = VirtualPathUtility.ToAppRelative (vpath);
277 RegisterTagName (tagPrefix + ":" + tagName);
278 RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, vpath);
281 ArrayList other_deps = new ArrayList ();
282 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
283 foreach (string s in other_deps)
285 AddAssembly (type.Assembly, true);
286 RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, type);
288 AddDependency (vpath);
289 } catch (ParseException pe) {
290 if (this is UserControlParser)
291 throw new ParseException (Location, pe.Message, pe);
296 internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
301 if (assembly != null && assembly.Length > 0)
302 ass = AddAssemblyByName (assembly);
304 RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
307 internal virtual void HandleOptions (object obj)
311 internal static string GetOneKey (Hashtable tbl)
313 foreach (object key in tbl.Keys)
314 return key.ToString ();
319 internal virtual void AddDirective (string directive, Hashtable atts)
322 var pageParserFilter = PageParserFilter;
324 if (String.Compare (directive, DefaultDirectiveName, true) == 0) {
326 bool allowMainDirective = allowedMainDirectives > 0;
328 bool allowMainDirective = false;
330 if (mainAttributes != null && !allowMainDirective)
331 ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
333 allowedMainDirectives--;
334 if (mainAttributes != null)
337 if (pageParserFilter != null)
338 pageParserFilter.PreprocessDirective (directive.ToLower (CultureInfo.InvariantCulture), atts);
341 mainAttributes = atts;
342 ProcessMainAttributes (mainAttributes);
346 else if (pageParserFilter != null)
347 pageParserFilter.PreprocessDirective (directive.ToLower (CultureInfo.InvariantCulture), atts);
350 int cmp = String.Compare ("Assembly", directive, true);
352 string name = GetString (atts, "Name", null);
353 string src = GetString (atts, "Src", null);
356 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
358 if (name == null && src == null)
359 ThrowParseException ("You gotta specify Src or Name");
361 if (name != null && src != null)
362 ThrowParseException ("Src and Name cannot be used together");
365 AddAssemblyByName (name);
367 GetAssemblyFromSource (src);
373 cmp = String.Compare ("Import", directive, true);
375 string namesp = GetString (atts, "Namespace", null);
377 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
383 cmp = String.Compare ("Implements", directive, true);
385 string ifacename = GetString (atts, "Interface", "");
388 ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
390 Type iface = LoadType (ifacename);
392 ThrowParseException ("Cannot find type " + ifacename);
394 if (!iface.IsInterface)
395 ThrowParseException (iface + " is not an interface");
397 AddInterface (iface.FullName);
401 cmp = String.Compare ("OutputCache", directive, true);
403 HttpResponse response = HttpContext.Current.Response;
404 if (response != null)
405 response.Cache.SetValidUntilExpires (true);
409 if (atts ["Duration"] == null)
410 ThrowParseException ("The directive is missing a 'duration' attribute.");
411 if (atts ["VaryByParam"] == null && atts ["VaryByControl"] == null)
412 ThrowParseException ("This directive is missing 'VaryByParam' " +
413 "or 'VaryByControl' attribute, which should be set to \"none\", \"*\", " +
414 "or a list of name/value pairs.");
416 foreach (DictionaryEntry entry in atts) {
417 string key = (string) entry.Key;
418 switch (key.ToLower ()) {
420 oc_duration = Int32.Parse ((string) entry.Value);
422 ThrowParseException ("The 'duration' attribute must be set " +
423 "to a positive integer value");
426 case "sqldependency":
427 oc_sqldependency = (string) entry.Value;
432 oc_nostore = Boolean.Parse ((string) entry.Value);
433 oc_parsed_params |= OutputCacheParsedParams.NoStore;
435 ThrowParseException ("The 'NoStore' attribute is case sensitive" +
436 " and must be set to 'true' or 'false'.");
441 oc_cacheprofile = (string) entry.Value;
442 oc_parsed_params |= OutputCacheParsedParams.CacheProfile;
445 case "varybycontentencodings":
446 oc_content_encodings = (string) entry.Value;
447 oc_parsed_params |= OutputCacheParsedParams.VaryByContentEncodings;
451 oc_param = (string) entry.Value;
452 if (String.Compare (oc_param, "none") == 0)
456 oc_header = (string) entry.Value;
458 oc_parsed_params |= OutputCacheParsedParams.VaryByHeader;
462 oc_custom = (string) entry.Value;
464 oc_parsed_params |= OutputCacheParsedParams.VaryByCustom;
468 if (!(this is PageParser))
472 oc_location = (OutputCacheLocation) Enum.Parse (
473 typeof (OutputCacheLocation), (string) entry.Value, true);
475 oc_parsed_params |= OutputCacheParsedParams.Location;
478 ThrowParseException ("The 'location' attribute is case sensitive and " +
479 "must be one of the following values: Any, Client, " +
480 "Downstream, Server, None, ServerAndClient.");
483 case "varybycontrol":
485 if (this is PageParser)
488 oc_controls = (string) entry.Value;
490 oc_parsed_params |= OutputCacheParsedParams.VaryByControl;
494 if (this is PageParser)
498 oc_shared = Boolean.Parse ((string) entry.Value);
500 ThrowParseException ("The 'shared' attribute is case sensitive" +
501 " and must be set to 'true' or 'false'.");
505 ThrowParseException ("The '" + key + "' attribute is not " +
506 "supported by the 'Outputcache' directive.");
515 ThrowParseException ("Unknown directive: " + directive);
518 internal Type LoadType (string typeName)
520 Type type = HttpApplication.LoadType (typeName);
523 Assembly asm = type.Assembly;
524 string location = asm.Location;
526 string dirname = Path.GetDirectoryName (location);
527 bool doAddAssembly = true;
528 if (dirname == HttpApplication.BinDirectory)
529 doAddAssembly = false;
532 AddAssembly (asm, true);
538 void AddAssembliesInBin ()
541 foreach (string s in HttpApplication.BinDirectoryAssemblies) {
543 asm = Assembly.LoadFrom (s);
544 assemblies.Add (asm.Location);
545 } catch (BadImageFormatException) {
552 internal virtual void AddInterface (string iface)
554 if (interfaces == null) {
556 interfaces = new List <string> ();
558 interfaces = new ArrayList ();
562 if (!interfaces.Contains (iface))
563 interfaces.Add (iface);
566 internal virtual void AddImport (string namesp)
568 if (namesp == null || namesp.Length == 0)
571 if (imports == null) {
573 imports = new List <string> ();
575 imports = new ArrayList ();
579 if (imports.Contains (namesp))
582 imports.Add (namesp);
584 AddAssemblyForNamespace (namesp);
589 void AddAssemblyForNamespace (string namesp)
591 if (binDirAssemblies == null)
592 binDirAssemblies = HttpApplication.BinDirectoryAssemblies;
593 if (binDirAssemblies.Length == 0)
596 if (namespacesCache == null)
597 namespacesCache = new Dictionary <string, bool> ();
598 else if (namespacesCache.ContainsKey (namesp))
601 foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
602 if (FindNamespaceInAssembly (asm, namesp))
605 IList tla = BuildManager.TopLevelAssemblies;
606 if (tla != null && tla.Count > 0) {
607 foreach (Assembly asm in tla) {
608 if (FindNamespaceInAssembly (asm, namesp))
614 foreach (string s in binDirAssemblies) {
615 a = Assembly.LoadFrom (s);
616 if (FindNamespaceInAssembly (a, namesp))
621 bool FindNamespaceInAssembly (Assembly asm, string namesp)
623 foreach (Type type in asm.GetTypes ()) {
624 if (String.Compare (type.Namespace, namesp, StringComparison.Ordinal) == 0) {
625 namespacesCache.Add (namesp, true);
626 AddAssembly (asm, true);
635 internal virtual void AddSourceDependency (string filename)
637 if (dependencies != null && dependencies.Contains (filename))
638 ThrowParseException ("Circular file references are not allowed. File: " + filename);
640 AddDependency (filename);
643 internal virtual void AddDependency (string filename)
645 if (filename == null || filename == String.Empty)
648 if (dependencies == null)
649 dependencies = new ArrayList ();
651 if (!dependencies.Contains (filename))
652 dependencies.Add (filename);
655 internal virtual void AddAssembly (Assembly assembly, bool fullPath)
657 if (assembly == null || assembly.Location == String.Empty)
661 anames = new Hashtable ();
663 string name = assembly.GetName ().Name;
664 string loc = assembly.Location;
666 if (!assemblies.Contains (loc)) {
667 assemblies.Add (loc);
671 anames [loc] = assembly;
673 if (!assemblies.Contains (name)) {
674 assemblies.Add (name);
677 anames [name] = assembly;
681 internal virtual Assembly AddAssemblyByFileName (string filename)
683 Assembly assembly = null;
684 Exception error = null;
687 assembly = Assembly.LoadFrom (filename);
688 } catch (Exception e) { error = e; }
690 if (assembly == null)
691 ThrowParseException ("Assembly " + filename + " not found", error);
693 AddAssembly (assembly, true);
697 internal virtual Assembly AddAssemblyByName (string name)
700 anames = new Hashtable ();
702 if (anames.Contains (name)) {
703 object o = anames [name];
710 Assembly assembly = null;
711 Exception error = null;
713 assembly = Assembly.Load (name);
714 } catch (Exception e) { error = e; }
716 if (assembly == null) {
718 assembly = Assembly.LoadWithPartialName (name);
719 } catch (Exception e) { error = e; }
722 if (assembly == null)
723 ThrowParseException ("Assembly " + name + " not found", error);
725 AddAssembly (assembly, true);
729 internal virtual void ProcessMainAttributes (Hashtable atts)
731 directiveLocation = new System.Web.Compilation.Location (Location);
734 CompilationSection compConfig;
736 CompilationConfiguration compConfig;
739 compConfig = CompilationConfig;
741 atts.Remove ("Description"); // ignored
743 atts.Remove ("CodeBehind"); // ignored
745 atts.Remove ("AspCompat"); // ignored
747 debug = GetBool (atts, "Debug", compConfig.Debug);
748 compilerOptions = GetString (atts, "CompilerOptions", "");
749 language = GetString (atts, "Language", "");
750 if (language.Length != 0)
751 implicitLanguage = false;
753 language = compConfig.DefaultLanguage;
755 strictOn = GetBool (atts, "Strict", compConfig.Strict);
756 explicitOn = GetBool (atts, "Explicit", compConfig.Explicit);
757 if (atts.ContainsKey ("LinePragmas"))
758 linePragmasOn = GetBool (atts, "LinePragmas", true);
760 string inherits = GetString (atts, "Inherits", null);
762 string srcRealPath = null;
764 // In ASP 2, the source file is actually integrated with
765 // the generated file via the use of partial classes. This
766 // means that the code file has to be confirmed, but not
767 // used at this point.
768 src = GetString (atts, "CodeFile", null);
769 codeFileBaseClass = GetString (atts, "CodeFileBaseClass", null);
771 if (src == null && codeFileBaseClass != null)
772 ThrowParseException ("The 'CodeFileBaseClass' attribute cannot be used without a 'CodeFile' attribute");
774 string legacySrc = GetString (atts, "Src", null);
775 if (legacySrc != null) {
776 legacySrc = UrlUtils.Combine (BaseVirtualDir, legacySrc);
777 GetAssemblyFromSource (legacySrc);
781 legacySrc = MapPath (legacySrc, false);
782 srcRealPath = legacySrc;
783 if (!File.Exists (srcRealPath))
784 ThrowParseException ("File " + src + " not found");
788 legacySrc = MapPath (legacySrc, false);
790 AddDependency (legacySrc);
793 if (!srcIsLegacy && src != null && inherits != null) {
794 // Make sure the source exists
795 src = UrlUtils.Combine (BaseVirtualDir, src);
796 srcRealPath = MapPath (src, false);
798 if (!HostingEnvironment.VirtualPathProvider.FileExists (src))
799 ThrowParseException ("File " + src + " not found");
801 // We are going to create a partial class that shares
802 // the same name as the inherits tag, so reset the
803 // name. The base type is changed because it is the
804 // code file's responsibilty to extend the classes
806 partialClassName = inherits;
808 // Add the code file as an option to the
809 // compiler. This lets both files be compiled at once.
810 compilerOptions += " \"" + srcRealPath + "\"";
812 if (codeFileBaseClass != null) {
814 codeFileBaseClassType = LoadType (codeFileBaseClass);
815 } catch (Exception) {
818 if (codeFileBaseClassType == null)
819 ThrowParseException ("Could not load type '{0}'", codeFileBaseClass);
821 } else if (inherits != null) {
822 // We just set the inherits directly because this is a
823 // Single-Page model.
824 SetBaseType (inherits);
827 string src = GetString (atts, "Src", null);
830 srcAssembly = GetAssemblyFromSource (src);
832 if (inherits != null)
833 SetBaseType (inherits);
836 if (VirtualPathUtility.IsAbsolute (src))
837 src = VirtualPathUtility.ToAppRelative (src);
841 className = GetString (atts, "ClassName", null);
842 if (className != null) {
844 string [] identifiers = className.Split ('.');
845 for (int i = 0; i < identifiers.Length; i++)
846 if (!CodeGenerator.IsValidLanguageIndependentIdentifier (identifiers [i]))
847 ThrowParseException (String.Format ("'{0}' is not a valid "
848 + "value for attribute 'classname'.", className));
850 if (!CodeGenerator.IsValidLanguageIndependentIdentifier (className))
851 ThrowParseException (String.Format ("'{0}' is not a valid "
852 + "value for attribute 'classname'.", className));
857 if (this is TemplateControlParser)
858 metaResourceKey = GetString (atts, "meta:resourcekey", null);
860 if (inherits != null && (this is PageParser || this is UserControlParser) && atts.Count > 0) {
861 if (unknownMainAttributes == null)
862 unknownMainAttributes = new List <UnknownAttributeDescriptor> ();
865 foreach (DictionaryEntry de in atts) {
866 key = de.Key as string;
867 val = de.Value as string;
869 if (String.IsNullOrEmpty (key) || String.IsNullOrEmpty (val))
871 CheckUnknownAttribute (key, val, inherits);
877 ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
881 void RegisterTagName (string tagName)
883 if (registeredTagNames == null)
884 registeredTagNames = new List <string> ();
886 if (registeredTagNames.Contains (tagName))
889 registeredTagNames.Add (tagName);
892 void CheckUnknownAttribute (string name, string val, string inherits)
894 MemberInfo mi = null;
895 bool missing = false;
896 string memberName = name.Trim ().ToLower (CultureInfo.InvariantCulture);
897 Type parent = codeFileBaseClassType;
903 MemberInfo[] infos = parent.GetMember (memberName,
904 MemberTypes.Field | MemberTypes.Property,
905 BindingFlags.Public | BindingFlags.Instance |
906 BindingFlags.IgnoreCase | BindingFlags.Static);
907 if (infos.Length != 0) {
908 // prefer public properties to public methods (it's what MS.NET does)
909 foreach (MemberInfo tmp in infos) {
910 if (tmp is PropertyInfo) {
919 } catch (Exception) {
923 ThrowParseException (
924 "Error parsing attribute '{0}': Type '{1}' does not have a public property named '{0}'",
925 memberName, inherits);
927 Type memberType = null;
928 if (mi is PropertyInfo) {
929 PropertyInfo pi = mi as PropertyInfo;
932 ThrowParseException (
933 "Error parsing attribute '{0}': The '{0}' property is read-only and cannot be set.",
935 memberType = pi.PropertyType;
936 } else if (mi is FieldInfo) {
937 memberType = ((FieldInfo)mi).FieldType;
939 ThrowParseException ("Could not determine member the kind of '{0}' in base type '{1}",
940 memberName, inherits);
941 TypeConverter converter = TypeDescriptor.GetConverter (memberType);
942 bool convertible = true;
945 if (converter == null || !converter.CanConvertFrom (typeof (string)))
950 value = converter.ConvertFromInvariantString (val);
951 } catch (Exception) {
957 ThrowParseException ("Error parsing attribute '{0}': Cannot create an object of type '{1}' from its string representation '{2}' for the '{3}' property.",
958 memberName, memberType, val, mi.Name);
960 UnknownAttributeDescriptor desc = new UnknownAttributeDescriptor (mi, value);
961 unknownMainAttributes.Add (desc);
965 internal void SetBaseType (string type)
968 if (type == null || type == DefaultBaseTypeName)
969 parent = DefaultBaseType;
973 if (parent == null) {
975 parent = LoadType (type);
978 if (srcAssembly != null)
979 parent = srcAssembly.GetType (type);
982 parent = LoadType (type);
986 ThrowParseException ("Cannot find type " + type);
988 if (!DefaultBaseType.IsAssignableFrom (parent))
989 ThrowParseException ("The parent type '" + type + "' does not derive from " + DefaultBaseType);
993 var pageParserFilter = PageParserFilter;
994 if (pageParserFilter != null && !pageParserFilter.AllowBaseType (parent))
995 throw new HttpException ("Base type '" + parent + "' is not allowed.");
1001 internal void SetLanguage (string language)
1003 this.language = language;
1004 implicitLanguage = false;
1007 internal void PushIncludeDir (string dir)
1009 if (includeDirs == null) {
1011 includeDirs = new Stack <string> (1);
1013 includeDirs = new Stack (1);
1017 includeDirs.Push (dir);
1020 internal string PopIncludeDir ()
1022 if (includeDirs == null || includeDirs.Count == 0)
1025 return includeDirs.Pop () as string;
1028 Assembly GetAssemblyFromSource (string vpath)
1030 vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
1031 string realPath = MapPath (vpath, false);
1032 if (!File.Exists (realPath))
1033 ThrowParseException ("File " + vpath + " not found");
1035 AddSourceDependency (vpath);
1037 CompilerResults result;
1041 CompilerParameters parameters;
1042 CodeDomProvider provider = BaseCompiler.CreateProvider (HttpContext.Current, language, out parameters, out tmp);
1043 if (provider == null)
1044 throw new HttpException ("Cannot find provider for language '" + language + "'.");
1046 AssemblyBuilder abuilder = new AssemblyBuilder (provider);
1047 abuilder.CompilerOptions = parameters;
1048 abuilder.AddAssemblyReference (BuildManager.GetReferencedAssemblies () as List <Assembly>);
1049 abuilder.AddCodeFile (realPath);
1050 result = abuilder.BuildAssembly (new VirtualPath (vpath));
1052 result = CachingCompiler.Compile (language, realPath, realPath, assemblies, Debug);
1054 if (result.NativeCompilerReturnValue != 0) {
1055 using (StreamReader reader = new StreamReader (realPath)) {
1056 throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
1060 AddAssembly (result.CompiledAssembly, true);
1061 return result.CompiledAssembly;
1064 internal abstract string DefaultBaseTypeName { get; }
1065 internal abstract string DefaultDirectiveName { get; }
1067 internal bool LinePragmasOn {
1068 get { return linePragmasOn; }
1072 internal byte[] MD5Checksum {
1073 get { return md5checksum; }
1074 set { md5checksum = value; }
1077 internal PageParserFilter PageParserFilter {
1079 if (pageParserFilter != null)
1080 return pageParserFilter;
1082 Type t = PageParserFilterType;
1086 pageParserFilter = Activator.CreateInstance (t) as PageParserFilter;
1087 pageParserFilter.Initialize (this);
1089 return pageParserFilter;
1093 internal Type PageParserFilterType {
1095 if (pageParserFilterType == null) {
1096 string typeName = PagesConfig.PageParserFilterType;
1097 if (String.IsNullOrEmpty (typeName))
1100 pageParserFilterType = HttpApplication.LoadType (typeName, true);
1103 return pageParserFilterType;
1108 internal Type DefaultBaseType {
1110 Type type = Type.GetType (DefaultBaseTypeName, true);
1116 internal ILocation DirectiveLocation {
1117 get { return directiveLocation; }
1120 internal string ParserDir {
1122 if (includeDirs == null || includeDirs.Count == 0)
1125 return includeDirs.Peek () as string;
1129 internal string InputFile
1131 get { return inputFile; }
1132 set { inputFile = value; }
1136 internal bool IsPartial {
1137 get { return (!srcIsLegacy && src != null); }
1140 internal string CodeBehindSource {
1149 internal string PartialClassName {
1150 get { return partialClassName; }
1153 internal string CodeFileBaseClass {
1154 get { return codeFileBaseClass; }
1157 internal string MetaResourceKey {
1158 get { return metaResourceKey; }
1161 internal Type CodeFileBaseClassType
1163 get { return codeFileBaseClassType; }
1166 internal List <UnknownAttributeDescriptor> UnknownMainAttributes
1168 get { return unknownMainAttributes; }
1172 internal string Text {
1173 get { return text; }
1174 set { text = value; }
1177 internal Type BaseType {
1179 if (baseType == null)
1180 SetBaseType (DefaultBaseTypeName);
1186 internal bool BaseTypeIsGlobal {
1187 get { return baseTypeIsGlobal; }
1188 set { baseTypeIsGlobal = value; }
1192 static long autoClassCounter = 0;
1195 internal string EncodeIdentifier (string value)
1197 if (value == null || value.Length == 0 || CodeGenerator.IsValidLanguageIndependentIdentifier (value))
1200 StringBuilder ret = new StringBuilder ();
1202 char ch = value [0];
1203 switch (Char.GetUnicodeCategory (ch)) {
1204 case UnicodeCategory.LetterNumber:
1205 case UnicodeCategory.LowercaseLetter:
1206 case UnicodeCategory.TitlecaseLetter:
1207 case UnicodeCategory.UppercaseLetter:
1208 case UnicodeCategory.OtherLetter:
1209 case UnicodeCategory.ModifierLetter:
1210 case UnicodeCategory.ConnectorPunctuation:
1214 case UnicodeCategory.DecimalDigitNumber:
1224 for (int i = 1; i < value.Length; i++) {
1226 switch (Char.GetUnicodeCategory (ch)) {
1227 case UnicodeCategory.LetterNumber:
1228 case UnicodeCategory.LowercaseLetter:
1229 case UnicodeCategory.TitlecaseLetter:
1230 case UnicodeCategory.UppercaseLetter:
1231 case UnicodeCategory.OtherLetter:
1232 case UnicodeCategory.ModifierLetter:
1233 case UnicodeCategory.ConnectorPunctuation:
1234 case UnicodeCategory.DecimalDigitNumber:
1235 case UnicodeCategory.NonSpacingMark:
1236 case UnicodeCategory.SpacingCombiningMark:
1237 case UnicodeCategory.Format:
1247 return ret.ToString ();
1250 internal string ClassName {
1252 if (className != null)
1256 string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
1259 if (String.IsNullOrEmpty (inputFile)) {
1261 using (StreamReader sr = Reader as StreamReader) {
1263 FileStream fr = sr.BaseStream as FileStream;
1271 if (String.IsNullOrEmpty (inFile)) {
1272 // generate a unique class name
1274 suffix = Interlocked.Increment (ref autoClassCounter);
1275 className = String.Format ("autoclass_nosource_{0:x}", suffix);
1279 if (StrUtils.StartsWith (inFile, physPath))
1280 className = inputFile.Substring (physPath.Length).ToLower (CultureInfo.InvariantCulture);
1283 className = Path.GetFileName (inputFile);
1284 className = EncodeIdentifier (className);
1290 internal List <ServerSideScript> Scripts {
1292 if (scripts == null)
1293 scripts = new List <ServerSideScript> ();
1299 internal List <string> Imports {
1300 get { return imports; }
1303 internal List <string> Interfaces {
1304 get { return interfaces; }
1307 internal ArrayList Scripts {
1309 if (scripts == null)
1310 scripts = new ArrayList ();
1316 internal ArrayList Imports {
1317 get { return imports; }
1320 internal ArrayList Interfaces {
1321 get { return interfaces; }
1325 internal ArrayList Assemblies {
1327 if (appAssemblyIndex != -1) {
1328 object o = assemblies [appAssemblyIndex];
1329 assemblies.RemoveAt (appAssemblyIndex);
1331 appAssemblyIndex = -1;
1338 internal RootBuilder RootBuilder {
1341 if (rootBuilder != null)
1343 AspGenerator generator = AspGenerator;
1344 if (generator != null)
1345 rootBuilder = generator.RootBuilder;
1349 set { rootBuilder = value; }
1352 internal ArrayList Dependencies {
1353 get { return dependencies; }
1354 set { dependencies = value; }
1357 internal string CompilerOptions {
1358 get { return compilerOptions; }
1361 internal string Language {
1362 get { return language; }
1365 internal bool ImplicitLanguage {
1366 get { return implicitLanguage; }
1369 internal bool StrictOn {
1370 get { return strictOn; }
1373 internal bool ExplicitOn {
1374 get { return explicitOn; }
1377 internal bool Debug {
1378 get { return debug; }
1381 internal bool OutputCache {
1382 get { return output_cache; }
1385 internal int OutputCacheDuration {
1386 get { return oc_duration; }
1390 internal OutputCacheParsedParams OutputCacheParsedParameters {
1391 get { return oc_parsed_params; }
1394 internal string OutputCacheSqlDependency {
1395 get { return oc_sqldependency; }
1398 internal string OutputCacheCacheProfile {
1399 get { return oc_cacheprofile; }
1402 internal string OutputCacheVaryByContentEncodings {
1403 get { return oc_content_encodings; }
1406 internal bool OutputCacheNoStore {
1407 get { return oc_nostore; }
1410 internal virtual TextReader Reader {
1411 get { return null; }
1416 internal string OutputCacheVaryByHeader {
1417 get { return oc_header; }
1420 internal string OutputCacheVaryByCustom {
1421 get { return oc_custom; }
1424 internal string OutputCacheVaryByControls {
1425 get { return oc_controls; }
1428 internal bool OutputCacheShared {
1429 get { return oc_shared; }
1432 internal OutputCacheLocation OutputCacheLocation {
1433 get { return oc_location; }
1436 internal string OutputCacheVaryByParam {
1437 get { return oc_param; }
1441 internal List <string> RegisteredTagNames {
1442 get { return registeredTagNames; }
1445 internal PagesSection PagesConfig {
1446 get { return GetConfigSection <PagesSection> ("system.web/pages") as PagesSection; }
1449 internal AspGenerator AspGenerator {
1454 internal PagesConfiguration PagesConfig {
1455 get { return PagesConfiguration.GetInstance (Context); }