CachingCompiler.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. //
  2. // System.Web.Compilation.CachingCompiler
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2002 Ximian, Inc (http://www.ximian.com)
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Diagnostics;
  12. using System.IO;
  13. using System.Text;
  14. using System.Web.UI;
  15. using System.Web.Util;
  16. namespace System.Web.Compilation
  17. {
  18. //TODO: caching should be done using System.Web.Caching, but that namespace still need some work.
  19. internal class CompilationCacheItem
  20. {
  21. CompilationResult result;
  22. DateTime reference;
  23. bool invalidated;
  24. public CompilationCacheItem (CompilationResult result)
  25. {
  26. this.result = result;
  27. try {
  28. this.reference = File.GetLastWriteTime (result.OutputFile);
  29. } catch (FileNotFoundException fnf){
  30. throw new FileNotFoundException (String.Format ("File: {0} at {1}", result.OutputFile, System.Environment.CurrentDirectory), fnf.FileName);
  31. }
  32. }
  33. public bool CheckDependencies ()
  34. {
  35. if (invalidated || result.Dependencies == null)
  36. return false;
  37. if (!File.Exists (result.OutputFile))
  38. return false;
  39. foreach (string s in result.Dependencies) {
  40. if (!File.Exists (s) || File.GetLastWriteTime (s) > reference) {
  41. invalidated = true;
  42. return false;
  43. }
  44. }
  45. return true;
  46. }
  47. public CompilationResult Result
  48. {
  49. get { return result; }
  50. }
  51. }
  52. internal class CompilationCache
  53. {
  54. static Hashtable cache;
  55. static CompilationCache instance = new CompilationCache ();
  56. private CompilationCache ()
  57. {
  58. }
  59. static CompilationCache ()
  60. {
  61. cache = new Hashtable ();
  62. }
  63. public static CompilationCache GetInstance ()
  64. {
  65. return instance;
  66. }
  67. public CompilationCacheItem this [string key]
  68. {
  69. get {
  70. return cache [key] as CompilationCacheItem;
  71. }
  72. set {
  73. cache [key] = value;
  74. }
  75. }
  76. }
  77. internal class CachingCompiler
  78. {
  79. static CompilationCache cache = CompilationCache.GetInstance ();
  80. string key;
  81. BaseCompiler compiler;
  82. public CachingCompiler (BaseCompiler compiler)
  83. {
  84. this.compiler = compiler;
  85. this.key = compiler.Key;
  86. }
  87. public static CompilationCacheItem GetCached (string key)
  88. {
  89. if (key == null)
  90. throw new ArgumentNullException ("key");
  91. CompilationCacheItem item = cache [key];
  92. if (item != null && item.CheckDependencies ())
  93. return item;
  94. return null;
  95. }
  96. static object compilationLock = new object ();
  97. public bool Compile (CompilationResult result)
  98. {
  99. if (compiler.SourceFile == null)
  100. throw new ArgumentException ("No source to compile!");
  101. result.Reset ();
  102. CompilationCacheItem item;
  103. item = GetCached (key);
  104. if (item != null) {
  105. result.CopyFrom (item.Result);
  106. return true;
  107. }
  108. lock (compilationLock) {
  109. item = GetCached (key);
  110. if (item != null) {
  111. result.CopyFrom (item.Result);
  112. return true;
  113. }
  114. RealCompile (result);
  115. cache [key] = new CompilationCacheItem (result);
  116. }
  117. return (result.ExitCode == 0);
  118. }
  119. void RealCompile (CompilationResult result)
  120. {
  121. StringBuilder options = new StringBuilder ("/target:library ");
  122. if (compiler.CompilerOptions != null)
  123. options.Append (compiler.CompilerOptions + ' ');
  124. options.AppendFormat ("/out:{0} ", compiler.TargetFile);
  125. options.Append (compiler.SourceFile);
  126. //Console.WriteLine ("mcs {0}", options);
  127. Process proc = new Process ();
  128. if (System.IO.Path.DirectorySeparatorChar == '\\')
  129. proc.StartInfo.FileName = "mcs.bat";
  130. else
  131. proc.StartInfo.FileName = "mcs";
  132. proc.StartInfo.Arguments = options.ToString ();
  133. proc.StartInfo.UseShellExecute = false;
  134. proc.StartInfo.RedirectStandardOutput = true;
  135. WebTrace.WriteLine ("{0} {1}", proc.StartInfo.FileName, options.ToString ());
  136. proc.Start ();
  137. string poutput = proc.StandardOutput.ReadToEnd();
  138. proc.WaitForExit ();
  139. result.ExitCode = proc.ExitCode;
  140. proc.Close ();
  141. proc = null;
  142. result.CompilerOutput = poutput;
  143. //Console.WriteLine ("output: {0}\n", poutput);
  144. result.OutputFile = compiler.TargetFile;
  145. }
  146. }
  147. }