SimpleWebHandlerParser.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. //
  2. // System.Web.UI.SimpleWebHandlerParser
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
  8. //
  9. using System;
  10. using System.CodeDom.Compiler;
  11. using System.Collections;
  12. using System.IO;
  13. using System.Reflection;
  14. using System.Text;
  15. using System.Web;
  16. using System.Web.Compilation;
  17. using System.Web.Configuration;
  18. using System.Web.Util;
  19. namespace System.Web.UI
  20. {
  21. public abstract class SimpleWebHandlerParser
  22. {
  23. HttpContext context;
  24. string vPath;
  25. string physPath;
  26. string className;
  27. string codeBehind;
  28. bool debug;
  29. string language;
  30. string program;
  31. bool gotDefault;
  32. ArrayList assemblies;
  33. ArrayList dependencies;
  34. Hashtable anames;
  35. string privateBinPath;
  36. string baseDir;
  37. string baseVDir;
  38. CompilationConfiguration compilationConfig;
  39. int appAssemblyIndex = -1;
  40. protected SimpleWebHandlerParser (HttpContext context, string virtualPath, string physicalPath)
  41. {
  42. this.context = context;
  43. this.vPath = virtualPath;
  44. this.physPath = physicalPath;
  45. AddDependency (physicalPath);
  46. assemblies = new ArrayList ();
  47. string location = Context.ApplicationInstance.AssemblyLocation;
  48. if (location != typeof (TemplateParser).Assembly.Location)
  49. appAssemblyIndex = assemblies.Add (location);
  50. assemblies.AddRange (CompilationConfig.Assemblies);
  51. if (CompilationConfig.AssembliesInBin)
  52. AddAssembliesInBin ();
  53. language = CompilationConfig.DefaultLanguage;
  54. GetDirectivesAndContent ();
  55. }
  56. [MonoTODO]
  57. protected Type GetCompiledTypeFromCache ()
  58. {
  59. return null;
  60. }
  61. void GetDirectivesAndContent ()
  62. {
  63. StreamReader reader = new StreamReader (File.OpenRead (physPath));
  64. string line;
  65. bool directiveFound = false;
  66. StringBuilder content = new StringBuilder ();
  67. while ((line = reader.ReadLine ()) != null) {
  68. string trimmed = line.Trim ();
  69. if (!directiveFound && trimmed == String.Empty)
  70. continue;
  71. if (trimmed.StartsWith ("<")) {
  72. ParseDirective (trimmed);
  73. directiveFound = true;
  74. continue;
  75. }
  76. content.Append (line + "\n");
  77. content.Append (reader.ReadToEnd ());
  78. }
  79. if (!gotDefault)
  80. throw new ParseException (null, "No @WebService directive found");
  81. this.program = content.ToString ();
  82. reader.Close ();
  83. }
  84. void TagParsed (ILocation location, System.Web.Compilation.TagType tagtype, string tagid, TagAttributes attributes)
  85. {
  86. if (tagtype != System.Web.Compilation.TagType.Directive)
  87. throw new ParseException (location, "Unexpected tag");
  88. if (String.Compare (tagid, DefaultDirectiveName, true) == 0) {
  89. AddDefaultDirective (location, attributes);
  90. } else if (String.Compare (tagid, "Assembly", true) == 0) {
  91. AddAssemblyDirective (location, attributes);
  92. } else {
  93. throw new ParseException (location, "Unexpected directive: " + tagid);
  94. }
  95. }
  96. void TextParsed (ILocation location, string text)
  97. {
  98. if (text.Trim () != "")
  99. throw new ParseException (location, "Text not allowed here");
  100. }
  101. void ParseError (ILocation location, string message)
  102. {
  103. throw new ParseException (location, message);
  104. }
  105. static string GetAndRemove (Hashtable table, string key)
  106. {
  107. string o = table [key] as string;
  108. table.Remove (key);
  109. return o;
  110. }
  111. void ParseDirective (string line)
  112. {
  113. AspParser parser = new AspParser (physPath, new StringReader (line));
  114. parser.Error += new ParseErrorHandler (ParseError);
  115. parser.TagParsed += new TagParsedHandler (TagParsed);
  116. parser.TextParsed += new TextParsedHandler (TextParsed);
  117. parser.Parse ();
  118. }
  119. internal virtual void AddDefaultDirective (ILocation location, TagAttributes attrs)
  120. {
  121. if (gotDefault)
  122. throw new ParseException (location, "duplicate " + DefaultDirectiveName + " directive");
  123. gotDefault = true;
  124. Hashtable attributes = attrs.GetDictionary (null);
  125. className = GetAndRemove (attributes, "class");
  126. if (className == null)
  127. throw new ParseException (null, "No Class attribute found.");
  128. string d = GetAndRemove (attributes, "debug");
  129. if (d != null) {
  130. debug = (String.Compare (d, "true", true) == 0);
  131. if (debug == false && String.Compare (d, "false", true) != 0)
  132. throw new ParseException (null, "Invalid value for Debug attribute");
  133. }
  134. language = GetAndRemove (attributes, "language");
  135. if (language == null)
  136. language = CompilationConfig.DefaultLanguage;
  137. codeBehind = GetAndRemove (attributes, "codebehind");
  138. if (attributes.Count > 0)
  139. throw new ParseException (location, "Unrecognized attribute in " +
  140. DefaultDirectiveName + " directive");
  141. }
  142. internal virtual void AddAssemblyDirective (ILocation location, TagAttributes attrs)
  143. {
  144. Hashtable tbl = attrs.GetDictionary (null);
  145. string name = GetAndRemove (tbl, "Name");
  146. string src = GetAndRemove (tbl, "Src");
  147. if (name == null && src == null)
  148. throw new ParseException (location, "You gotta specify Src or Name");
  149. if (name != null && src != null)
  150. throw new ParseException (location, "Src and Name cannot be used together");
  151. if (name != null) {
  152. AddAssemblyByName (name, location);
  153. } else {
  154. GetAssemblyFromSource (src, location);
  155. }
  156. if (tbl.Count > 0)
  157. throw new ParseException (location, "Unrecognized attribute in Assembly directive");
  158. }
  159. internal virtual void AddAssembly (Assembly assembly, bool fullPath)
  160. {
  161. if (anames == null)
  162. anames = new Hashtable ();
  163. string name = assembly.GetName ().Name;
  164. string loc = assembly.Location;
  165. if (fullPath) {
  166. if (!assemblies.Contains (loc)) {
  167. assemblies.Add (loc);
  168. }
  169. anames [name] = loc;
  170. anames [loc] = assembly;
  171. } else {
  172. if (!assemblies.Contains (name)) {
  173. assemblies.Add (name);
  174. }
  175. anames [name] = assembly;
  176. }
  177. }
  178. internal virtual Assembly AddAssemblyByName (string name, ILocation location)
  179. {
  180. if (anames == null)
  181. anames = new Hashtable ();
  182. if (anames.Contains (name)) {
  183. object o = anames [name];
  184. if (o is string)
  185. o = anames [o];
  186. return (Assembly) o;
  187. }
  188. bool fullpath = true;
  189. Assembly assembly = LoadAssemblyFromBin (name);
  190. if (assembly != null) {
  191. AddAssembly (assembly, fullpath);
  192. return assembly;
  193. }
  194. try {
  195. assembly = Assembly.LoadWithPartialName (name);
  196. string loc = assembly.Location;
  197. fullpath = (Path.GetDirectoryName (loc) == PrivateBinPath);
  198. } catch (Exception e) {
  199. throw new ParseException (location, "Assembly " + name + " not found", e);
  200. }
  201. AddAssembly (assembly, fullpath);
  202. return assembly;
  203. }
  204. void AddAssembliesInBin ()
  205. {
  206. if (!Directory.Exists (PrivateBinPath))
  207. return;
  208. string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
  209. foreach (string dll in binDlls) {
  210. try {
  211. Assembly assembly = Assembly.LoadFrom (dll);
  212. AddAssembly (assembly, true);
  213. } catch (Exception e) {
  214. throw new Exception ("Error while loading " + dll, e);
  215. }
  216. }
  217. }
  218. Assembly LoadAssemblyFromBin (string name)
  219. {
  220. Assembly assembly;
  221. if (!Directory.Exists (PrivateBinPath))
  222. return null;
  223. string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
  224. foreach (string dll in binDlls) {
  225. string fn = Path.GetFileName (dll);
  226. fn = Path.ChangeExtension (fn, null);
  227. if (fn != name)
  228. continue;
  229. assembly = Assembly.LoadFrom (dll);
  230. return assembly;
  231. }
  232. return null;
  233. }
  234. Assembly GetAssemblyFromSource (string vpath, ILocation location)
  235. {
  236. vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
  237. string realPath = context.Request.MapPath (vpath);
  238. if (!File.Exists (realPath))
  239. throw new ParseException (location, "File " + vpath + " not found");
  240. AddDependency (realPath);
  241. CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies);
  242. if (result.NativeCompilerReturnValue != 0) {
  243. StreamReader reader = new StreamReader (realPath);
  244. throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
  245. }
  246. AddAssembly (result.CompiledAssembly, true);
  247. return result.CompiledAssembly;
  248. }
  249. internal Type GetTypeFromBin (string typeName)
  250. {
  251. if (!Directory.Exists (PrivateBinPath))
  252. throw new HttpException (String.Format ("Type {0} not found.", typeName));
  253. string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
  254. Type result = null;
  255. foreach (string dll in binDlls) {
  256. Assembly assembly = Assembly.LoadFrom (dll);
  257. Type type = assembly.GetType (typeName, false);
  258. if (type != null) {
  259. if (result != null)
  260. throw new HttpException (String.Format ("Type {0} is not unique.", typeName));
  261. result = type;
  262. }
  263. }
  264. if (result == null)
  265. throw new HttpException (String.Format ("Type {0} not found.", typeName));
  266. return result;
  267. }
  268. internal virtual void AddDependency (string filename)
  269. {
  270. if (dependencies == null)
  271. dependencies = new ArrayList ();
  272. if (!dependencies.Contains (filename))
  273. dependencies.Add (filename);
  274. }
  275. // Properties
  276. protected abstract string DefaultDirectiveName { get; }
  277. internal HttpContext Context {
  278. get { return context; }
  279. }
  280. internal string VirtualPath {
  281. get { return vPath; }
  282. }
  283. internal string PhysicalPath {
  284. get { return physPath; }
  285. }
  286. internal string ClassName {
  287. get { return className; }
  288. }
  289. internal string CodeBehind {
  290. get { return codeBehind; }
  291. }
  292. internal bool Debug {
  293. get { return debug; }
  294. }
  295. internal string Language {
  296. get { return language; }
  297. }
  298. internal string Program {
  299. get { return program; }
  300. }
  301. internal ArrayList Assemblies {
  302. get {
  303. if (appAssemblyIndex != -1) {
  304. object o = assemblies [appAssemblyIndex];
  305. assemblies.RemoveAt (appAssemblyIndex);
  306. assemblies.Add (o);
  307. appAssemblyIndex = -1;
  308. }
  309. return assemblies;
  310. }
  311. }
  312. internal ArrayList Dependencies {
  313. get { return dependencies; }
  314. }
  315. internal string PrivateBinPath {
  316. get {
  317. if (privateBinPath != null)
  318. return privateBinPath;
  319. AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
  320. privateBinPath = setup.PrivateBinPath;
  321. if (!Path.IsPathRooted (privateBinPath)) {
  322. string appbase = setup.ApplicationBase;
  323. if (appbase.StartsWith ("file://")) {
  324. appbase = appbase.Substring (7);
  325. if (Path.DirectorySeparatorChar != '/')
  326. appbase = appbase.Replace ('/', Path.DirectorySeparatorChar);
  327. }
  328. privateBinPath = Path.Combine (appbase, privateBinPath);
  329. }
  330. return privateBinPath;
  331. }
  332. }
  333. internal string BaseDir {
  334. get {
  335. if (baseDir == null)
  336. baseDir = context.Request.MapPath (BaseVirtualDir);
  337. return baseDir;
  338. }
  339. }
  340. internal virtual string BaseVirtualDir {
  341. get {
  342. if (baseVDir == null)
  343. baseVDir = UrlUtils.GetDirectory (context.Request.FilePath);
  344. return baseVDir;
  345. }
  346. }
  347. internal CompilationConfiguration CompilationConfig {
  348. get {
  349. if (compilationConfig == null)
  350. compilationConfig = CompilationConfiguration.GetInstance (context);
  351. return compilationConfig;
  352. }
  353. }
  354. }
  355. }