2
0

TemplateParser.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. //
  2. // System.Web.UI.TemplateParser
  3. //
  4. // Authors:
  5. // Duncan Mak ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. //
  8. // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
  9. //
  10. using System;
  11. using System.CodeDom.Compiler;
  12. using System.Collections;
  13. using System.IO;
  14. using System.Reflection;
  15. using System.Web;
  16. using System.Web.Compilation;
  17. using System.Web.Util;
  18. namespace System.Web.UI
  19. {
  20. public abstract class TemplateParser : BaseParser
  21. {
  22. string inputFile;
  23. string text;
  24. string privateBinPath;
  25. Hashtable mainAttributes;
  26. ArrayList dependencies;
  27. ArrayList assemblies;
  28. Hashtable anames;
  29. ArrayList imports;
  30. ArrayList interfaces;
  31. ArrayList scripts;
  32. Type baseType;
  33. string className;
  34. RootBuilder rootBuilder;
  35. bool debug;
  36. string compilerOptions;
  37. string language;
  38. internal TemplateParser ()
  39. {
  40. imports = new ArrayList ();
  41. imports.Add ("System");
  42. imports.Add ("System.Collections");
  43. imports.Add ("System.Collections.Specialized");
  44. imports.Add ("System.Configuration");
  45. imports.Add ("System.Text");
  46. imports.Add ("System.Text.RegularExpressions");
  47. imports.Add ("System.Web");
  48. imports.Add ("System.Web.Caching");
  49. imports.Add ("System.Web.Security");
  50. imports.Add ("System.Web.SessionState");
  51. imports.Add ("System.Web.UI");
  52. imports.Add ("System.Web.UI.WebControls");
  53. imports.Add ("System.Web.UI.HtmlControls");
  54. assemblies = new ArrayList ();
  55. assemblies.Add ("System.dll");
  56. assemblies.Add ("System.Drawing.dll");
  57. assemblies.Add ("System.Data.dll");
  58. assemblies.Add ("System.Web.dll");
  59. assemblies.Add ("System.Xml.dll");
  60. AddAssembliesInBin ();
  61. }
  62. protected abstract Type CompileIntoType ();
  63. internal virtual void HandleOptions (object obj)
  64. {
  65. }
  66. internal static string GetOneKey (Hashtable tbl)
  67. {
  68. foreach (object key in tbl.Keys)
  69. return key.ToString ();
  70. return null;
  71. }
  72. internal virtual void AddDirective (string directive, Hashtable atts)
  73. {
  74. if (String.Compare (directive, DefaultDirectiveName, true) == 0) {
  75. if (mainAttributes != null)
  76. ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
  77. mainAttributes = atts;
  78. ProcessMainAttributes (mainAttributes);
  79. return;
  80. }
  81. int cmp = String.Compare ("Assembly", directive, true);
  82. if (cmp == 0) {
  83. string name = GetString (atts, "Name", null);
  84. string src = GetString (atts, "Src", null);
  85. if (atts.Count > 0)
  86. ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
  87. if (name == null && src == null)
  88. ThrowParseException ("You gotta specify Src or Name");
  89. if (name != null && src != null)
  90. ThrowParseException ("Src and Name cannot be used together");
  91. if (name != null) {
  92. AddAssemblyByName (name);
  93. } else {
  94. GetAssemblyFromSource (src);
  95. }
  96. return;
  97. }
  98. cmp = String.Compare ("Import", directive, true);
  99. if (cmp == 0) {
  100. string namesp = GetString (atts, "Namespace", null);
  101. if (atts.Count > 0)
  102. ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
  103. if (namesp != null && namesp != "")
  104. AddImport (namesp);
  105. return;
  106. }
  107. cmp = String.Compare ("Implements", directive, true);
  108. if (cmp == 0) {
  109. string ifacename = GetString (atts, "Interface", "");
  110. if (atts.Count > 0)
  111. ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
  112. Type iface = LoadType (ifacename);
  113. if (iface == null)
  114. ThrowParseException ("Cannot find type " + ifacename);
  115. if (!iface.IsInterface)
  116. ThrowParseException (iface + " is not an interface");
  117. AddInterface (iface.FullName);
  118. return;
  119. }
  120. ThrowParseException ("Unknown directive: " + directive);
  121. }
  122. internal Type LoadType (string typeName)
  123. {
  124. // First try loaded assemblies, then try assemblies in Bin directory.
  125. // By now i do this 'by hand' but may be this is a runtime/gac task.
  126. Type type = null;
  127. Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
  128. foreach (Assembly ass in assemblies) {
  129. type = ass.GetType (typeName);
  130. if (type != null) {
  131. AddAssembly (ass, false);
  132. AddDependency (ass.Location);
  133. return type;
  134. }
  135. }
  136. return null;
  137. }
  138. void AddAssembliesInBin ()
  139. {
  140. if (!Directory.Exists (PrivateBinPath))
  141. return;
  142. string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
  143. foreach (string dll in binDlls) {
  144. Assembly assembly = Assembly.LoadFrom (dll);
  145. AddAssembly (assembly, true);
  146. }
  147. }
  148. Assembly LoadAssemblyFromBin (string name)
  149. {
  150. Assembly assembly;
  151. if (!Directory.Exists (PrivateBinPath))
  152. return null;
  153. string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
  154. foreach (string dll in binDlls) {
  155. string fn = Path.GetFileName (dll);
  156. fn = Path.ChangeExtension (fn, null);
  157. if (fn != name)
  158. continue;
  159. assembly = Assembly.LoadFrom (dll);
  160. return assembly;
  161. }
  162. return null;
  163. }
  164. internal virtual void AddInterface (string iface)
  165. {
  166. if (interfaces == null)
  167. interfaces = new ArrayList ();
  168. if (!interfaces.Contains (iface))
  169. interfaces.Add (iface);
  170. }
  171. internal virtual void AddImport (string namesp)
  172. {
  173. if (imports == null)
  174. imports = new ArrayList ();
  175. if (!imports.Contains (namesp))
  176. imports.Add (namesp);
  177. }
  178. internal virtual void AddDependency (string filename)
  179. {
  180. if (dependencies == null)
  181. dependencies = new ArrayList ();
  182. if (!dependencies.Contains (filename))
  183. dependencies.Add (filename);
  184. }
  185. internal virtual void AddAssembly (Assembly assembly, bool fullPath)
  186. {
  187. if (anames == null)
  188. anames = new Hashtable ();
  189. string name = assembly.GetName ().Name;
  190. string loc = assembly.Location;
  191. if (fullPath) {
  192. if (!assemblies.Contains (loc)) {
  193. assemblies.Add (loc);
  194. }
  195. anames [name] = loc;
  196. anames [loc] = assembly;
  197. } else {
  198. if (!assemblies.Contains (name)) {
  199. assemblies.Add (name);
  200. }
  201. anames [name] = assembly;
  202. }
  203. }
  204. internal virtual Assembly AddAssemblyByName (string name)
  205. {
  206. if (anames == null)
  207. anames = new Hashtable ();
  208. if (anames.Contains (name)) {
  209. object o = anames [name];
  210. if (o is string)
  211. o = anames [o];
  212. return (Assembly) o;
  213. }
  214. bool fullpath = true;
  215. Assembly assembly = LoadAssemblyFromBin (name);
  216. if (assembly != null) {
  217. AddAssembly (assembly, fullpath);
  218. return assembly;
  219. }
  220. try {
  221. assembly = Assembly.Load (name);
  222. string loc = assembly.Location;
  223. fullpath = (Path.GetDirectoryName (loc) == PrivateBinPath);
  224. } catch (Exception e) {
  225. ThrowParseException ("Assembly " + name + " not found", e);
  226. }
  227. AddAssembly (assembly, fullpath);
  228. return assembly;
  229. }
  230. internal virtual void ProcessMainAttributes (Hashtable atts)
  231. {
  232. atts.Remove ("Description"); // ignored
  233. atts.Remove ("CodeBehind"); // ignored
  234. debug = GetBool (atts, "Debug", true);
  235. compilerOptions = GetString (atts, "CompilerOptions", null);
  236. language = GetString (atts, "Language", "C#");
  237. if (String.Compare (language, "c#", true) != 0)
  238. ThrowParseException ("Only C# supported.");
  239. string src = GetString (atts, "Src", null);
  240. Assembly srcAssembly = null;
  241. if (src != null)
  242. srcAssembly = GetAssemblyFromSource (src);
  243. string inherits = GetString (atts, "Inherits", null);
  244. if (inherits != null) {
  245. Type parent;
  246. if (srcAssembly != null)
  247. parent = srcAssembly.GetType (inherits);
  248. else
  249. parent = LoadType (inherits);
  250. if (parent == null)
  251. ThrowParseException ("Cannot find type " + inherits);
  252. if (!DefaultBaseType.IsAssignableFrom (parent))
  253. ThrowParseException ("The parent type does not derive from " + DefaultBaseType);
  254. baseType = parent;
  255. }
  256. className = GetString (atts, "ClassName", null);
  257. if (atts.Count > 0)
  258. ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
  259. }
  260. Assembly GetAssemblyFromSource (string vpath)
  261. {
  262. vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
  263. string realPath = MapPath (vpath, false);
  264. if (!File.Exists (realPath))
  265. ThrowParseException ("File " + vpath + " not found");
  266. AddDependency (realPath);
  267. CompilerResults result = CachingCompiler.Compile (realPath, realPath, assemblies);
  268. if (result.NativeCompilerReturnValue != 0) {
  269. StringWriter writer = new StringWriter();
  270. StreamReader reader = new StreamReader (realPath);
  271. throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
  272. }
  273. AddAssembly (result.CompiledAssembly, true);
  274. return result.CompiledAssembly;
  275. }
  276. internal abstract Type DefaultBaseType { get; }
  277. internal abstract string DefaultDirectiveName { get; }
  278. internal string InputFile
  279. {
  280. get { return inputFile; }
  281. set { inputFile = value; }
  282. }
  283. internal string Text
  284. {
  285. get { return text; }
  286. set { text = value; }
  287. }
  288. internal Type BaseType
  289. {
  290. get {
  291. if (baseType == null)
  292. baseType = DefaultBaseType;
  293. return baseType;
  294. }
  295. }
  296. internal string ClassName {
  297. get {
  298. if (className != null)
  299. return className;
  300. className = Path.GetFileName (inputFile).Replace ('.', '_');
  301. className = className.Replace ('-', '_');
  302. className = className.Replace (' ', '_');
  303. return className;
  304. }
  305. }
  306. internal string PrivateBinPath {
  307. get {
  308. if (privateBinPath != null)
  309. return privateBinPath;
  310. AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
  311. privateBinPath = setup.PrivateBinPath;
  312. if (!Path.IsPathRooted (privateBinPath)) {
  313. string appbase = setup.ApplicationBase;
  314. if (appbase.StartsWith ("file://")) {
  315. appbase = appbase.Substring (7);
  316. if (Path.DirectorySeparatorChar != '/')
  317. appbase = appbase.Replace ('/', Path.DirectorySeparatorChar);
  318. }
  319. privateBinPath = Path.Combine (appbase, privateBinPath);
  320. }
  321. return privateBinPath;
  322. }
  323. }
  324. internal ArrayList Scripts {
  325. get {
  326. if (scripts == null)
  327. scripts = new ArrayList ();
  328. return scripts;
  329. }
  330. }
  331. internal ArrayList Imports {
  332. get { return imports; }
  333. }
  334. internal ArrayList Assemblies {
  335. get { return assemblies; }
  336. }
  337. internal ArrayList Interfaces {
  338. get { return interfaces; }
  339. }
  340. internal RootBuilder RootBuilder {
  341. get { return rootBuilder; }
  342. set { rootBuilder = value; }
  343. }
  344. internal ArrayList Dependencies {
  345. get { return dependencies; }
  346. }
  347. internal string CompilerOptions {
  348. get { return compilerOptions; }
  349. }
  350. internal string Language {
  351. get { return language; }
  352. }
  353. internal bool Debug {
  354. get { return debug; }
  355. }
  356. }
  357. }