BuildManager.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461
  1. //
  2. // System.Web.Compilation.BuildManager
  3. //
  4. // Authors:
  5. // Chris Toshok ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Marek Habersack ([email protected])
  8. //
  9. // (C) 2006-2009 Novell, Inc (http://www.novell.com)
  10. //
  11. //
  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:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  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.
  30. //
  31. using System;
  32. using System.CodeDom;
  33. using System.CodeDom.Compiler;
  34. using System.Collections;
  35. using System.Collections.Generic;
  36. using System.Collections.Specialized;
  37. using System.ComponentModel;
  38. using System.IO;
  39. using System.Reflection;
  40. using System.Text;
  41. using System.Threading;
  42. using System.Xml;
  43. using System.Web;
  44. using System.Web.Caching;
  45. using System.Web.Configuration;
  46. using System.Web.Hosting;
  47. using System.Web.Util;
  48. #if NET_4_0
  49. using System.Runtime.Versioning;
  50. #endif
  51. namespace System.Web.Compilation
  52. {
  53. public sealed class BuildManager
  54. {
  55. internal const string FAKE_VIRTUAL_PATH_PREFIX = "/@@MonoFakeVirtualPath@@";
  56. const string BUILD_MANAGER_VIRTUAL_PATH_CACHE_PREFIX = "@@Build_Manager@@";
  57. static int BUILD_MANAGER_VIRTUAL_PATH_CACHE_PREFIX_LENGTH = BUILD_MANAGER_VIRTUAL_PATH_CACHE_PREFIX.Length;
  58. static readonly object bigCompilationLock = new object ();
  59. static readonly object virtualPathsToIgnoreLock = new object ();
  60. static readonly char[] virtualPathsToIgnoreSplitChars = {','};
  61. static EventHandlerList events = new EventHandlerList ();
  62. static object buildManagerRemoveEntryEvent = new object ();
  63. static bool hosted;
  64. static Dictionary <string, bool> virtualPathsToIgnore;
  65. static bool virtualPathsToIgnoreChecked;
  66. static bool haveVirtualPathsToIgnore;
  67. static List <Assembly> AppCode_Assemblies = new List<Assembly>();
  68. static List <Assembly> TopLevel_Assemblies = new List<Assembly>();
  69. static Dictionary <Type, CodeDomProvider> codeDomProviders;
  70. static Dictionary <string, BuildManagerCacheItem> buildCache;
  71. static List <Assembly> referencedAssemblies;
  72. static List <Assembly> configReferencedAssemblies;
  73. static bool getReferencedAssembliesInvoked;
  74. static int buildCount;
  75. static bool is_precompiled;
  76. static bool allowReferencedAssembliesCaching;
  77. #if NET_4_0
  78. static List <Assembly> dynamicallyRegisteredAssemblies;
  79. static bool? batchCompilationEnabled;
  80. static FrameworkName targetFramework;
  81. static bool preStartMethodsDone;
  82. static bool preStartMethodsRunning;
  83. #endif
  84. //static bool updatable; unused
  85. static Dictionary<string, PreCompilationData> precompiled;
  86. // This is here _only_ for the purpose of unit tests!
  87. internal static bool suppressDebugModeMessages;
  88. #if SYSTEMCORE_DEP
  89. static ReaderWriterLockSlim buildCacheLock;
  90. #else
  91. static ReaderWriterLock buildCacheLock;
  92. #endif
  93. static ulong recursionDepth;
  94. internal static bool AllowReferencedAssembliesCaching {
  95. get { return allowReferencedAssembliesCaching; }
  96. set { allowReferencedAssembliesCaching = value; }
  97. }
  98. internal static bool IsPrecompiled {
  99. get { return is_precompiled; }
  100. }
  101. internal static event BuildManagerRemoveEntryEventHandler RemoveEntry {
  102. add { events.AddHandler (buildManagerRemoveEntryEvent, value); }
  103. remove { events.RemoveHandler (buildManagerRemoveEntryEvent, value); }
  104. }
  105. #if NET_4_0
  106. internal static bool PreStartMethodsRunning {
  107. get { return preStartMethodsRunning;
  108. }
  109. }
  110. public static bool? BatchCompilationEnabled {
  111. get { return batchCompilationEnabled; }
  112. set {
  113. if (preStartMethodsDone)
  114. throw new InvalidOperationException ("This method cannot be called after the application's pre-start initialization stage.");
  115. batchCompilationEnabled = value;
  116. }
  117. }
  118. public static FrameworkName TargetFramework {
  119. get {
  120. if (targetFramework == null) {
  121. CompilationSection cs = CompilationConfig;
  122. string framework;
  123. if (cs == null)
  124. framework = null;
  125. else
  126. framework = cs.TargetFramework;
  127. if (String.IsNullOrEmpty (framework))
  128. targetFramework = new FrameworkName (".NETFramework,Version=v4.0");
  129. else
  130. targetFramework = new FrameworkName (framework);
  131. }
  132. return targetFramework;
  133. }
  134. }
  135. #endif
  136. internal static bool BatchMode {
  137. get {
  138. #if NET_4_0
  139. if (batchCompilationEnabled != null)
  140. return (bool)batchCompilationEnabled;
  141. #endif
  142. if (!hosted)
  143. return false; // Fix for bug #380985
  144. CompilationSection cs = CompilationConfig;
  145. if (cs == null)
  146. return true;
  147. return cs.Batch;
  148. }
  149. }
  150. // Assemblies built from the App_Code directory
  151. public static IList CodeAssemblies {
  152. get { return AppCode_Assemblies; }
  153. }
  154. internal static CompilationSection CompilationConfig {
  155. get { return WebConfigurationManager.GetWebApplicationSection ("system.web/compilation") as CompilationSection; }
  156. }
  157. internal static bool HaveResources {
  158. get; set;
  159. }
  160. internal static IList TopLevelAssemblies {
  161. get { return TopLevel_Assemblies; }
  162. }
  163. static BuildManager ()
  164. {
  165. hosted = (AppDomain.CurrentDomain.GetData (ApplicationHost.MonoHostedDataKey) as string) == "yes";
  166. buildCache = new Dictionary <string, BuildManagerCacheItem> (RuntimeHelpers.StringEqualityComparerCulture);
  167. #if SYSTEMCORE_DEP
  168. buildCacheLock = new ReaderWriterLockSlim ();
  169. #else
  170. buildCacheLock = new ReaderWriterLock ();
  171. #endif
  172. referencedAssemblies = new List <Assembly> ();
  173. recursionDepth = 0;
  174. string appPath = HttpRuntime.AppDomainAppPath;
  175. string precomp_name = null;
  176. is_precompiled = String.IsNullOrEmpty (appPath) ? false : File.Exists ((precomp_name = Path.Combine (appPath, "PrecompiledApp.config")));
  177. if (is_precompiled)
  178. is_precompiled = LoadPrecompilationInfo (precomp_name);
  179. }
  180. #if NET_4_0
  181. internal static void AssertPreStartMethodsRunning ()
  182. {
  183. if (!BuildManager.PreStartMethodsRunning)
  184. throw new InvalidOperationException ("This method must be called during the application's pre-start initialization stage.");
  185. }
  186. #endif
  187. // Deal with precompiled sites deployed in a different virtual path
  188. static void FixVirtualPaths ()
  189. {
  190. if (precompiled == null)
  191. return;
  192. string [] parts;
  193. int skip = -1;
  194. foreach (string vpath in precompiled.Keys) {
  195. parts = vpath.Split ('/');
  196. for (int i = 0; i < parts.Length; i++) {
  197. if (String.IsNullOrEmpty (parts [i]))
  198. continue;
  199. // The path must be rooted, otherwise PhysicalPath returned
  200. // below will be relative to the current request path and
  201. // File.Exists will return a false negative. See bug #546053
  202. string test_path = "/" + String.Join ("/", parts, i, parts.Length - i);
  203. VirtualPath result = GetAbsoluteVirtualPath (test_path);
  204. if (result != null && File.Exists (result.PhysicalPath)) {
  205. skip = i - 1;
  206. break;
  207. }
  208. }
  209. }
  210. string app_vpath = HttpRuntime.AppDomainAppVirtualPath;
  211. if (skip == -1 || (skip == 0 && app_vpath == "/"))
  212. return;
  213. if (!app_vpath.EndsWith ("/"))
  214. app_vpath = app_vpath + "/";
  215. Dictionary<string, PreCompilationData> copy = new Dictionary<string, PreCompilationData> (precompiled);
  216. precompiled.Clear ();
  217. foreach (KeyValuePair<string,PreCompilationData> entry in copy) {
  218. parts = entry.Key.Split ('/');
  219. string new_path;
  220. if (String.IsNullOrEmpty (parts [0]))
  221. new_path = app_vpath + String.Join ("/", parts, skip + 1, parts.Length - skip - 1);
  222. else
  223. new_path = app_vpath + String.Join ("/", parts, skip, parts.Length - skip);
  224. entry.Value.VirtualPath = new_path;
  225. precompiled.Add (new_path, entry.Value);
  226. }
  227. }
  228. static bool LoadPrecompilationInfo (string precomp_config)
  229. {
  230. using (XmlTextReader reader = new XmlTextReader (precomp_config)) {
  231. reader.MoveToContent ();
  232. if (reader.Name != "precompiledApp")
  233. return false;
  234. /* unused
  235. if (reader.HasAttributes)
  236. while (reader.MoveToNextAttribute ())
  237. if (reader.Name == "updatable") {
  238. updatable = (reader.Value == "true");
  239. break;
  240. }
  241. */
  242. }
  243. string [] compiled = Directory.GetFiles (HttpRuntime.BinDirectory, "*.compiled");
  244. foreach (string str in compiled)
  245. LoadCompiled (str);
  246. FixVirtualPaths ();
  247. return true;
  248. }
  249. static void LoadCompiled (string filename)
  250. {
  251. using (XmlTextReader reader = new XmlTextReader (filename)) {
  252. reader.MoveToContent ();
  253. if (reader.Name == "preserve" && reader.HasAttributes) {
  254. reader.MoveToNextAttribute ();
  255. string val = reader.Value;
  256. // 1 -> app_code subfolder - add the assembly to CodeAssemblies
  257. // 2 -> ashx
  258. // 3 -> ascx, aspx
  259. // 6 -> app_code - add the assembly to CodeAssemblies
  260. // 8 -> global.asax
  261. // 9 -> App_GlobalResources - set the assembly for HttpContext
  262. if (reader.Name == "resultType" && (val == "2" || val == "3" || val == "8"))
  263. LoadPageData (reader, true);
  264. else if (val == "1" || val == "6") {
  265. PreCompilationData pd = LoadPageData (reader, false);
  266. CodeAssemblies.Add (Assembly.Load (pd.AssemblyFileName));
  267. } else if (val == "9") {
  268. PreCompilationData pd = LoadPageData (reader, false);
  269. HttpContext.AppGlobalResourcesAssembly = Assembly.Load (pd.AssemblyFileName);
  270. }
  271. }
  272. }
  273. }
  274. class PreCompilationData {
  275. public string VirtualPath;
  276. public string AssemblyFileName;
  277. public string TypeName;
  278. public Type Type;
  279. }
  280. static PreCompilationData LoadPageData (XmlTextReader reader, bool store)
  281. {
  282. PreCompilationData pc_data = new PreCompilationData ();
  283. while (reader.MoveToNextAttribute ()) {
  284. string name = reader.Name;
  285. if (name == "virtualPath")
  286. pc_data.VirtualPath = VirtualPathUtility.RemoveTrailingSlash (reader.Value);
  287. else if (name == "assembly")
  288. pc_data.AssemblyFileName = reader.Value;
  289. else if (name == "type")
  290. pc_data.TypeName = reader.Value;
  291. }
  292. if (store) {
  293. if (precompiled == null)
  294. precompiled = new Dictionary<string, PreCompilationData> (RuntimeHelpers.StringEqualityComparerCulture);
  295. precompiled.Add (pc_data.VirtualPath, pc_data);
  296. }
  297. return pc_data;
  298. }
  299. static void AddAssembly (Assembly asm, List <Assembly> al)
  300. {
  301. if (al.Contains (asm))
  302. return;
  303. al.Add (asm);
  304. }
  305. static void AddPathToIgnore (string vp)
  306. {
  307. if (virtualPathsToIgnore == null)
  308. virtualPathsToIgnore = new Dictionary <string, bool> (RuntimeHelpers.StringEqualityComparerCulture);
  309. VirtualPath path = GetAbsoluteVirtualPath (vp);
  310. string vpAbsolute = path.Absolute;
  311. if (!virtualPathsToIgnore.ContainsKey (vpAbsolute)) {
  312. virtualPathsToIgnore.Add (vpAbsolute, true);
  313. haveVirtualPathsToIgnore = true;
  314. }
  315. string vpRelative = path.AppRelative;
  316. if (!virtualPathsToIgnore.ContainsKey (vpRelative)) {
  317. virtualPathsToIgnore.Add (vpRelative, true);
  318. haveVirtualPathsToIgnore = true;
  319. }
  320. if (!virtualPathsToIgnore.ContainsKey (vp)) {
  321. virtualPathsToIgnore.Add (vp, true);
  322. haveVirtualPathsToIgnore = true;
  323. }
  324. }
  325. internal static void AddToReferencedAssemblies (Assembly asm)
  326. {
  327. // should not be used
  328. }
  329. static void AssertVirtualPathExists (VirtualPath virtualPath)
  330. {
  331. string realpath;
  332. bool dothrow = false;
  333. if (virtualPath.IsFake) {
  334. realpath = virtualPath.PhysicalPath;
  335. if (!File.Exists (realpath) && !Directory.Exists (realpath))
  336. dothrow = true;
  337. } else {
  338. VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
  339. string vpAbsolute = virtualPath.Absolute;
  340. if (!vpp.FileExists (vpAbsolute) && !vpp.DirectoryExists (vpAbsolute))
  341. dothrow = true;
  342. }
  343. if (dothrow)
  344. throw new HttpException (404, "The file '" + virtualPath + "' does not exist.", virtualPath.Absolute);
  345. }
  346. static void Build (VirtualPath vp)
  347. {
  348. AssertVirtualPathExists (vp);
  349. CompilationSection cs = CompilationConfig;
  350. lock (bigCompilationLock) {
  351. bool entryExists;
  352. if (HasCachedItemNoLock (vp.Absolute, out entryExists))
  353. return;
  354. if (recursionDepth == 0)
  355. referencedAssemblies.Clear ();
  356. recursionDepth++;
  357. try {
  358. BuildInner (vp, cs != null ? cs.Debug : false);
  359. if (entryExists && recursionDepth <= 1)
  360. // We count only update builds - first time a file
  361. // (or a batch) is built doesn't count.
  362. buildCount++;
  363. } finally {
  364. // See http://support.microsoft.com/kb/319947
  365. if (buildCount > cs.NumRecompilesBeforeAppRestart)
  366. HttpRuntime.UnloadAppDomain ();
  367. recursionDepth--;
  368. }
  369. }
  370. }
  371. // This method assumes it is being called with the big compilation lock held
  372. static void BuildInner (VirtualPath vp, bool debug)
  373. {
  374. var builder = new BuildManagerDirectoryBuilder (vp);
  375. bool recursive = recursionDepth > 1;
  376. List <BuildProviderGroup> builderGroups = builder.Build (IsSingleBuild (vp, recursive));
  377. if (builderGroups == null)
  378. return;
  379. string vpabsolute = vp.Absolute;
  380. int buildHash = (vpabsolute.GetHashCode () | (int)DateTime.Now.Ticks) + (int)recursionDepth;
  381. string assemblyBaseName;
  382. AssemblyBuilder abuilder;
  383. CompilerType ct;
  384. int attempts;
  385. bool singleBuild, needMainVpBuild;
  386. CompilationException compilationError;
  387. // Each group becomes a separate assembly.
  388. foreach (BuildProviderGroup group in builderGroups) {
  389. needMainVpBuild = false;
  390. compilationError = null;
  391. assemblyBaseName = null;
  392. if (group.Count == 1) {
  393. if (recursive || !group.Master)
  394. assemblyBaseName = String.Format ("{0}_{1}.{2:x}.", group.NamePrefix, VirtualPathUtility.GetFileName (group [0].VirtualPath), buildHash);
  395. singleBuild = true;
  396. } else
  397. singleBuild = false;
  398. if (assemblyBaseName == null)
  399. assemblyBaseName = group.NamePrefix + "_";
  400. ct = group.CompilerType;
  401. attempts = 3;
  402. while (attempts > 0) {
  403. abuilder = new AssemblyBuilder (vp, CreateDomProvider (ct), assemblyBaseName);
  404. abuilder.CompilerOptions = ct.CompilerParameters;
  405. abuilder.AddAssemblyReference (GetReferencedAssemblies () as List <Assembly>);
  406. try {
  407. GenerateAssembly (abuilder, group, vp, debug);
  408. attempts = 0;
  409. } catch (CompilationException ex) {
  410. attempts--;
  411. if (singleBuild)
  412. throw new HttpException ("Single file build failed.", ex);
  413. if (attempts == 0) {
  414. needMainVpBuild = true;
  415. compilationError = ex;
  416. break;
  417. }
  418. CompilerResults results = ex.Results;
  419. if (results == null)
  420. throw new HttpException ("No results returned from failed compilation.", ex);
  421. else
  422. RemoveFailedAssemblies (vpabsolute, ex, abuilder, group, results, debug);
  423. }
  424. }
  425. if (needMainVpBuild) {
  426. // One last attempt - try to build just the requested path
  427. // if it's not built yet or just return without throwing the
  428. // exception if it has already been built.
  429. if (HasCachedItemNoLock (vpabsolute)) {
  430. if (debug)
  431. DescribeCompilationError ("Path '{0}' built successfully, but a compilation exception has been thrown for other files:",
  432. compilationError, vpabsolute);
  433. return;
  434. };
  435. // This will trigger a recursive build of the requested vp,
  436. // which means only the vp alone will be built (or not);
  437. Build (vp);
  438. if (HasCachedItemNoLock (vpabsolute)) {
  439. if (debug)
  440. DescribeCompilationError ("Path '{0}' built successfully, but a compilation exception has been thrown for other files:",
  441. compilationError, vpabsolute);
  442. return;
  443. }
  444. // In theory this code is unreachable. If the recursive
  445. // build of the main vp failed, then it should have thrown
  446. // the build exception.
  447. throw new HttpException ("Requested virtual path build failed.", compilationError);
  448. }
  449. }
  450. }
  451. static CodeDomProvider CreateDomProvider (CompilerType ct)
  452. {
  453. if (codeDomProviders == null)
  454. codeDomProviders = new Dictionary <Type, CodeDomProvider> ();
  455. Type type = ct.CodeDomProviderType;
  456. if (type == null) {
  457. CompilationSection cs = CompilationConfig;
  458. CompilerType tmp = GetDefaultCompilerTypeForLanguage (cs.DefaultLanguage, cs);
  459. if (tmp != null)
  460. type = tmp.CodeDomProviderType;
  461. }
  462. if (type == null)
  463. return null;
  464. CodeDomProvider ret;
  465. if (codeDomProviders.TryGetValue (type, out ret))
  466. return ret;
  467. ret = Activator.CreateInstance (type) as CodeDomProvider;
  468. if (ret == null)
  469. return null;
  470. codeDomProviders.Add (type, ret);
  471. return ret;
  472. }
  473. #if NET_4_0
  474. internal static void CallPreStartMethods ()
  475. {
  476. if (preStartMethodsDone)
  477. return;
  478. preStartMethodsRunning = true;
  479. MethodInfo mi = null;
  480. try {
  481. List <MethodInfo> methods = LoadPreStartMethodsFromAssemblies (GetReferencedAssemblies () as List <Assembly>);
  482. if (methods == null || methods.Count == 0)
  483. return;
  484. foreach (MethodInfo m in methods) {
  485. mi = m;
  486. m.Invoke (null, null);
  487. }
  488. } catch (Exception ex) {
  489. throw new HttpException (
  490. String.Format ("The pre-application start initialization method {0} on type {1} threw an exception with the following error message: {2}",
  491. mi != null ? mi.Name : "UNKNOWN",
  492. mi != null ? mi.DeclaringType.FullName : "UNKNOWN",
  493. ex.Message),
  494. ex
  495. );
  496. } finally {
  497. preStartMethodsRunning = false;
  498. preStartMethodsDone = true;
  499. }
  500. }
  501. static List <MethodInfo> LoadPreStartMethodsFromAssemblies (List <Assembly> assemblies)
  502. {
  503. if (assemblies == null || assemblies.Count == 0)
  504. return null;
  505. var ret = new List <MethodInfo> ();
  506. object[] attributes;
  507. Type type;
  508. PreApplicationStartMethodAttribute attr;
  509. foreach (Assembly asm in assemblies) {
  510. try {
  511. attributes = asm.GetCustomAttributes (typeof (PreApplicationStartMethodAttribute), false);
  512. if (attributes == null || attributes.Length == 0)
  513. continue;
  514. attr = attributes [0] as PreApplicationStartMethodAttribute;
  515. type = attr.Type;
  516. if (type == null)
  517. continue;
  518. } catch {
  519. continue;
  520. }
  521. MethodInfo mi;
  522. Exception error = null;
  523. try {
  524. if (type.IsPublic)
  525. mi = type.GetMethod (attr.MethodName, BindingFlags.Static | BindingFlags.Public, null, new Type[] {}, null);
  526. else
  527. mi = null;
  528. } catch (Exception ex) {
  529. error = ex;
  530. mi = null;
  531. }
  532. if (mi == null)
  533. throw new HttpException (
  534. String.Format (
  535. "The method specified by the PreApplicationStartMethodAttribute on assembly '{0}' cannot be resolved. Type: '{1}', MethodName: '{2}'. Verify that the type is public and the method is public and static (Shared in Visual Basic).",
  536. asm.FullName,
  537. type.FullName,
  538. attr.MethodName),
  539. error
  540. );
  541. ret.Add (mi);
  542. }
  543. return ret;
  544. }
  545. public static Type GetGlobalAsaxType ()
  546. {
  547. Type ret = HttpApplicationFactory.AppType;
  548. if (!preStartMethodsRunning)
  549. throw new InvalidOperationException ("This method cannot be called during the application's pre-start initialization stage.");
  550. return ret;
  551. }
  552. public static Stream CreateCachedFile (string fileName)
  553. {
  554. if (fileName != null && (fileName == String.Empty || fileName.IndexOf (Path.DirectorySeparatorChar) != -1))
  555. throw new ArgumentException ("Value does not fall within the expected range.");
  556. string path = Path.Combine (HttpRuntime.CodegenDir, fileName);
  557. return new FileStream (path, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
  558. }
  559. public static Stream ReadCachedFile (string fileName)
  560. {
  561. if (fileName != null && (fileName == String.Empty || fileName.IndexOf (Path.DirectorySeparatorChar) != -1))
  562. throw new ArgumentException ("Value does not fall within the expected range.");
  563. string path = Path.Combine (HttpRuntime.CodegenDir, fileName);
  564. if (!File.Exists (path))
  565. return null;
  566. return new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.None);
  567. }
  568. [MonoDocumentationNote ("Fully implemented but no info on application pre-init stage is available yet.")]
  569. public static void AddReferencedAssembly (Assembly assembly)
  570. {
  571. if (assembly == null)
  572. throw new ArgumentNullException ("assembly");
  573. Type ret = HttpApplicationFactory.AppType;
  574. if (preStartMethodsDone)
  575. throw new InvalidOperationException ("This method cannot be called after the application's pre-start initialization stage.");
  576. if (dynamicallyRegisteredAssemblies == null)
  577. dynamicallyRegisteredAssemblies = new List <Assembly> ();
  578. if (!dynamicallyRegisteredAssemblies.Contains (assembly))
  579. dynamicallyRegisteredAssemblies.Add (assembly);
  580. }
  581. [MonoTODO ("A no-op until we use IWebObjectFactory internally. Always returns null.")]
  582. public static IWebObjectFactory GetObjectFactory (string virtualPath, bool throwIfNotFound)
  583. {
  584. return null;
  585. }
  586. #endif
  587. public static object CreateInstanceFromVirtualPath (string virtualPath, Type requiredBaseType)
  588. {
  589. return CreateInstanceFromVirtualPath (GetAbsoluteVirtualPath (virtualPath), requiredBaseType);
  590. }
  591. internal static object CreateInstanceFromVirtualPath (VirtualPath virtualPath, Type requiredBaseType)
  592. {
  593. if (requiredBaseType == null)
  594. throw new NullReferenceException (); // This is what MS does, but
  595. // from somewhere else.
  596. Type type = GetCompiledType (virtualPath);
  597. if (type == null)
  598. return null;
  599. if (!requiredBaseType.IsAssignableFrom (type))
  600. throw new HttpException (500,
  601. String.Format ("Type '{0}' does not inherit from '{1}'.", type.FullName, requiredBaseType.FullName));
  602. return Activator.CreateInstance (type, null);
  603. }
  604. static void DescribeCompilationError (string format, CompilationException ex, params object[] parms)
  605. {
  606. StringBuilder sb = new StringBuilder ();
  607. string newline = Environment.NewLine;
  608. if (parms != null)
  609. sb.AppendFormat (format + newline, parms);
  610. else
  611. sb.Append (format + newline);
  612. CompilerResults results = ex != null ? ex.Results : null;
  613. if (results == null)
  614. sb.Append ("No compiler error information present." + newline);
  615. else {
  616. sb.Append ("Compiler errors:" + newline);
  617. foreach (CompilerError error in results.Errors)
  618. sb.Append (" " + error.ToString () + newline);
  619. }
  620. if (ex != null) {
  621. sb.Append (newline + "Exception thrown:" + newline);
  622. sb.Append (ex.ToString ());
  623. }
  624. ShowDebugModeMessage (sb.ToString ());
  625. }
  626. static BuildProvider FindBuildProviderForPhysicalPath (string path, BuildProviderGroup group, HttpRequest req)
  627. {
  628. if (req == null || String.IsNullOrEmpty (path))
  629. return null;
  630. foreach (BuildProvider bp in group) {
  631. if (String.Compare (path, req.MapPath (bp.VirtualPath), RuntimeHelpers.StringComparison) == 0)
  632. return bp;
  633. }
  634. return null;
  635. }
  636. static void GenerateAssembly (AssemblyBuilder abuilder, BuildProviderGroup group, VirtualPath vp, bool debug)
  637. {
  638. IDictionary <string, bool> deps;
  639. BuildManagerCacheItem bmci;
  640. string bvp, vpabsolute = vp.Absolute;
  641. StringBuilder sb;
  642. string newline;
  643. int failedCount = 0;
  644. if (debug) {
  645. newline = Environment.NewLine;
  646. sb = new StringBuilder ("Code generation for certain virtual paths in a batch failed. Those files have been removed from the batch." + newline);
  647. sb.Append ("Since you're running in debug mode, here's some more information about the error:" + newline);
  648. } else {
  649. newline = null;
  650. sb = null;
  651. }
  652. List <BuildProvider> failedBuildProviders = null;
  653. StringComparison stringComparison = RuntimeHelpers.StringComparison;
  654. foreach (BuildProvider bp in group) {
  655. bvp = bp.VirtualPath;
  656. if (HasCachedItemNoLock (bvp))
  657. continue;
  658. try {
  659. bp.GenerateCode (abuilder);
  660. } catch (Exception ex) {
  661. if (String.Compare (bvp, vpabsolute, stringComparison) == 0) {
  662. if (ex is CompilationException || ex is ParseException)
  663. throw;
  664. throw new HttpException ("Code generation failed.", ex);
  665. }
  666. if (failedBuildProviders == null)
  667. failedBuildProviders = new List <BuildProvider> ();
  668. failedBuildProviders.Add (bp);
  669. failedCount++;
  670. if (sb != null) {
  671. if (failedCount > 1)
  672. sb.Append (newline);
  673. sb.AppendFormat ("Failed file virtual path: {0}; Exception: {1}{2}{1}", bp.VirtualPath, newline, ex);
  674. }
  675. continue;
  676. }
  677. deps = bp.ExtractDependencies ();
  678. if (deps != null) {
  679. foreach (var dep in deps) {
  680. bmci = GetCachedItemNoLock (dep.Key);
  681. if (bmci == null || bmci.BuiltAssembly == null)
  682. continue;
  683. abuilder.AddAssemblyReference (bmci.BuiltAssembly);
  684. }
  685. }
  686. }
  687. if (sb != null && failedCount > 0)
  688. ShowDebugModeMessage (sb.ToString ());
  689. if (failedBuildProviders != null) {
  690. foreach (BuildProvider bp in failedBuildProviders)
  691. group.Remove (bp);
  692. }
  693. foreach (Assembly asm in referencedAssemblies) {
  694. if (asm == null)
  695. continue;
  696. abuilder.AddAssemblyReference (asm);
  697. }
  698. CompilerResults results = abuilder.BuildAssembly (vp);
  699. // No results is not an error - it is possible that the assembly builder contained only .asmx and
  700. // .ashx files which had no body, just the directive. In such case, no code unit or code file is added
  701. // to the assembly builder and, in effect, no assembly is produced but there are STILL types that need
  702. // to be added to the cache.
  703. Assembly compiledAssembly = results != null ? results.CompiledAssembly : null;
  704. bool locked = false;
  705. try {
  706. #if SYSTEMCORE_DEP
  707. buildCacheLock.EnterWriteLock ();
  708. #else
  709. buildCacheLock.AcquireWriterLock (-1);
  710. #endif
  711. locked = true;
  712. if (compiledAssembly != null)
  713. referencedAssemblies.Add (compiledAssembly);
  714. foreach (BuildProvider bp in group) {
  715. if (HasCachedItemNoLock (bp.VirtualPath))
  716. continue;
  717. StoreInCache (bp, compiledAssembly, results);
  718. }
  719. } finally {
  720. if (locked) {
  721. #if SYSTEMCORE_DEP
  722. buildCacheLock.ExitWriteLock ();
  723. #else
  724. buildCacheLock.ReleaseWriterLock ();
  725. #endif
  726. }
  727. }
  728. }
  729. static VirtualPath GetAbsoluteVirtualPath (string virtualPath)
  730. {
  731. string vp;
  732. if (!VirtualPathUtility.IsRooted (virtualPath)) {
  733. HttpContext ctx = HttpContext.Current;
  734. HttpRequest req = ctx != null ? ctx.Request : null;
  735. if (req != null) {
  736. string fileDir = req.FilePath;
  737. if (!String.IsNullOrEmpty (fileDir) && String.Compare (fileDir, "/", StringComparison.Ordinal) != 0)
  738. fileDir = VirtualPathUtility.GetDirectory (fileDir);
  739. else
  740. fileDir = "/";
  741. vp = VirtualPathUtility.Combine (fileDir, virtualPath);
  742. } else
  743. throw new HttpException ("No context, cannot map paths.");
  744. } else
  745. vp = virtualPath;
  746. return new VirtualPath (vp);
  747. }
  748. [MonoTODO ("Not implemented, always returns null")]
  749. public static BuildDependencySet GetCachedBuildDependencySet (HttpContext context, string virtualPath)
  750. {
  751. return null; // null is ok here until we store the dependency set in the Cache.
  752. }
  753. #if NET_4_0
  754. [MonoTODO ("Not implemented, always returns null")]
  755. public static BuildDependencySet GetCachedBuildDependencySet (HttpContext context, string virtualPath, bool ensureIsUpToDate)
  756. {
  757. return null; // null is ok here until we store the dependency set in the Cache.
  758. }
  759. #endif
  760. static BuildManagerCacheItem GetCachedItem (string vp)
  761. {
  762. bool locked = false;
  763. try {
  764. #if SYSTEMCORE_DEP
  765. buildCacheLock.EnterReadLock ();
  766. #else
  767. buildCacheLock.AcquireReaderLock (-1);
  768. #endif
  769. locked = true;
  770. return GetCachedItemNoLock (vp);
  771. } finally {
  772. if (locked) {
  773. #if SYSTEMCORE_DEP
  774. buildCacheLock.ExitReadLock ();
  775. #else
  776. buildCacheLock.ReleaseReaderLock ();
  777. #endif
  778. }
  779. }
  780. }
  781. static BuildManagerCacheItem GetCachedItemNoLock (string vp)
  782. {
  783. BuildManagerCacheItem ret;
  784. if (buildCache.TryGetValue (vp, out ret))
  785. return ret;
  786. return null;
  787. }
  788. internal static Type GetCodeDomProviderType (BuildProvider provider)
  789. {
  790. CompilerType codeCompilerType;
  791. Type codeDomProviderType = null;
  792. codeCompilerType = provider.CodeCompilerType;
  793. if (codeCompilerType != null)
  794. codeDomProviderType = codeCompilerType.CodeDomProviderType;
  795. if (codeDomProviderType == null)
  796. throw new HttpException (String.Concat ("Provider '", provider, " 'fails to specify the compiler type."));
  797. return codeDomProviderType;
  798. }
  799. static Type GetPrecompiledType (string virtualPath)
  800. {
  801. PreCompilationData pc_data;
  802. if (precompiled != null && precompiled.TryGetValue (virtualPath, out pc_data)) {
  803. if (pc_data.Type == null) {
  804. pc_data.Type = Type.GetType (pc_data.TypeName + ", " + pc_data.AssemblyFileName, true);
  805. }
  806. return pc_data.Type;
  807. }
  808. return null;
  809. }
  810. internal static Type GetPrecompiledApplicationType ()
  811. {
  812. if (!is_precompiled)
  813. return null;
  814. Type apptype = GetPrecompiledType (VirtualPathUtility.Combine (HttpRuntime.AppDomainAppVirtualPath, "Global.asax"));
  815. if (apptype == null)
  816. apptype = GetPrecompiledType (VirtualPathUtility.Combine (HttpRuntime.AppDomainAppVirtualPath , "global.asax"));
  817. return apptype;
  818. }
  819. public static Assembly GetCompiledAssembly (string virtualPath)
  820. {
  821. return GetCompiledAssembly (GetAbsoluteVirtualPath (virtualPath));
  822. }
  823. internal static Assembly GetCompiledAssembly (VirtualPath virtualPath)
  824. {
  825. string vpabsolute = virtualPath.Absolute;
  826. if (is_precompiled) {
  827. Type type = GetPrecompiledType (vpabsolute);
  828. if (type != null)
  829. return type.Assembly;
  830. }
  831. BuildManagerCacheItem bmci = GetCachedItem (vpabsolute);
  832. if (bmci != null)
  833. return bmci.BuiltAssembly;
  834. Build (virtualPath);
  835. bmci = GetCachedItem (vpabsolute);
  836. if (bmci != null)
  837. return bmci.BuiltAssembly;
  838. return null;
  839. }
  840. public static Type GetCompiledType (string virtualPath)
  841. {
  842. return GetCompiledType (GetAbsoluteVirtualPath (virtualPath));
  843. }
  844. internal static Type GetCompiledType (VirtualPath virtualPath)
  845. {
  846. string vpabsolute = virtualPath.Absolute;
  847. if (is_precompiled) {
  848. Type type = GetPrecompiledType (vpabsolute);
  849. if (type != null)
  850. return type;
  851. }
  852. BuildManagerCacheItem bmci = GetCachedItem (vpabsolute);
  853. if (bmci != null) {
  854. ReferenceAssemblyInCompilation (bmci);
  855. return bmci.Type;
  856. }
  857. Build (virtualPath);
  858. bmci = GetCachedItem (vpabsolute);
  859. if (bmci != null) {
  860. ReferenceAssemblyInCompilation (bmci);
  861. return bmci.Type;
  862. }
  863. return null;
  864. }
  865. public static string GetCompiledCustomString (string virtualPath)
  866. {
  867. return GetCompiledCustomString (GetAbsoluteVirtualPath (virtualPath));
  868. }
  869. internal static string GetCompiledCustomString (VirtualPath virtualPath)
  870. {
  871. string vpabsolute = virtualPath.Absolute;
  872. BuildManagerCacheItem bmci = GetCachedItem (vpabsolute);
  873. if (bmci != null)
  874. return bmci.CompiledCustomString;
  875. Build (virtualPath);
  876. bmci = GetCachedItem (vpabsolute);
  877. if (bmci != null)
  878. return bmci.CompiledCustomString;
  879. return null;
  880. }
  881. internal static CompilerType GetDefaultCompilerTypeForLanguage (string language, CompilationSection configSection)
  882. {
  883. return GetDefaultCompilerTypeForLanguage (language, configSection, true);
  884. }
  885. internal static CompilerType GetDefaultCompilerTypeForLanguage (string language, CompilationSection configSection, bool throwOnMissing)
  886. {
  887. // MS throws when accesing a Hashtable, we do here.
  888. if (language == null || language.Length == 0)
  889. throw new ArgumentNullException ("language");
  890. CompilationSection config;
  891. if (configSection == null)
  892. config = WebConfigurationManager.GetWebApplicationSection ("system.web/compilation") as CompilationSection;
  893. else
  894. config = configSection;
  895. Compiler compiler = config.Compilers.Get (language);
  896. CompilerParameters p;
  897. Type type;
  898. if (compiler != null) {
  899. type = HttpApplication.LoadType (compiler.Type, true);
  900. p = new CompilerParameters ();
  901. p.CompilerOptions = compiler.CompilerOptions;
  902. p.WarningLevel = compiler.WarningLevel;
  903. SetCommonParameters (config, p, type, language);
  904. return new CompilerType (type, p);
  905. }
  906. if (CodeDomProvider.IsDefinedLanguage (language)) {
  907. CompilerInfo info = CodeDomProvider.GetCompilerInfo (language);
  908. p = info.CreateDefaultCompilerParameters ();
  909. type = info.CodeDomProviderType;
  910. SetCommonParameters (config, p, type, language);
  911. return new CompilerType (type, p);
  912. }
  913. if (throwOnMissing)
  914. throw new HttpException (String.Concat ("No compiler for language '", language, "'."));
  915. return null;
  916. }
  917. public static ICollection GetReferencedAssemblies ()
  918. {
  919. if (getReferencedAssembliesInvoked)
  920. return configReferencedAssemblies;
  921. if (allowReferencedAssembliesCaching)
  922. getReferencedAssembliesInvoked = true;
  923. if (configReferencedAssemblies == null)
  924. configReferencedAssemblies = new List <Assembly> ();
  925. else if (getReferencedAssembliesInvoked)
  926. configReferencedAssemblies.Clear ();
  927. CompilationSection compConfig = WebConfigurationManager.GetWebApplicationSection ("system.web/compilation") as CompilationSection;
  928. if (compConfig == null)
  929. return configReferencedAssemblies;
  930. bool addAssembliesInBin = false;
  931. foreach (AssemblyInfo info in compConfig.Assemblies) {
  932. if (info.Assembly == "*")
  933. addAssembliesInBin = is_precompiled ? false : true;
  934. else
  935. LoadAssembly (info, configReferencedAssemblies);
  936. }
  937. foreach (Assembly topLevelAssembly in TopLevelAssemblies)
  938. configReferencedAssemblies.Add (topLevelAssembly);
  939. foreach (string assLocation in WebConfigurationManager.ExtraAssemblies)
  940. LoadAssembly (assLocation, configReferencedAssemblies);
  941. #if NET_4_0
  942. if (dynamicallyRegisteredAssemblies != null)
  943. foreach (Assembly registeredAssembly in dynamicallyRegisteredAssemblies)
  944. configReferencedAssemblies.Add (registeredAssembly);
  945. #endif
  946. // Precompiled sites unconditionally load all assemblies from bin/ (fix for
  947. // bug #502016)
  948. if (is_precompiled || addAssembliesInBin) {
  949. foreach (string s in HttpApplication.BinDirectoryAssemblies) {
  950. try {
  951. LoadAssembly (s, configReferencedAssemblies);
  952. } catch (BadImageFormatException) {
  953. // ignore silently
  954. }
  955. }
  956. }
  957. return configReferencedAssemblies;
  958. }
  959. // The 2 GetType() overloads work on the global.asax, App_GlobalResources, App_WebReferences or App_Browsers
  960. public static Type GetType (string typeName, bool throwOnError)
  961. {
  962. return GetType (typeName, throwOnError, false);
  963. }
  964. public static Type GetType (string typeName, bool throwOnError, bool ignoreCase)
  965. {
  966. Type ret = null;
  967. try {
  968. foreach (Assembly asm in TopLevel_Assemblies) {
  969. ret = asm.GetType (typeName, throwOnError, ignoreCase);
  970. if (ret != null)
  971. break;
  972. }
  973. } catch (Exception ex) {
  974. throw new HttpException ("Failed to find the specified type.", ex);
  975. }
  976. return ret;
  977. }
  978. public static ICollection GetVirtualPathDependencies (string virtualPath)
  979. {
  980. return GetVirtualPathDependencies (virtualPath, null);
  981. }
  982. internal static ICollection GetVirtualPathDependencies (string virtualPath, BuildProvider bprovider)
  983. {
  984. BuildProvider provider = bprovider;
  985. if (provider == null) {
  986. CompilationSection cs = CompilationConfig;
  987. if (cs == null)
  988. return null;
  989. provider = BuildManagerDirectoryBuilder.GetBuildProvider (virtualPath, cs.BuildProviders);
  990. }
  991. if (provider == null)
  992. return null;
  993. IDictionary <string, bool> deps = provider.ExtractDependencies ();
  994. if (deps == null)
  995. return null;
  996. return (ICollection)deps.Keys;
  997. }
  998. internal static bool HasCachedItemNoLock (string vp, out bool entryExists)
  999. {
  1000. BuildManagerCacheItem item;
  1001. if (buildCache.TryGetValue (vp, out item)) {
  1002. entryExists = true;
  1003. return item != null;
  1004. }
  1005. entryExists = false;
  1006. return false;
  1007. }
  1008. internal static bool HasCachedItemNoLock (string vp)
  1009. {
  1010. bool dummy;
  1011. return HasCachedItemNoLock (vp, out dummy);
  1012. }
  1013. internal static bool IgnoreVirtualPath (string virtualPath)
  1014. {
  1015. if (!virtualPathsToIgnoreChecked) {
  1016. lock (virtualPathsToIgnoreLock) {
  1017. if (!virtualPathsToIgnoreChecked)
  1018. LoadVirtualPathsToIgnore ();
  1019. virtualPathsToIgnoreChecked = true;
  1020. }
  1021. }
  1022. if (!haveVirtualPathsToIgnore)
  1023. return false;
  1024. if (virtualPathsToIgnore.ContainsKey (virtualPath))
  1025. return true;
  1026. return false;
  1027. }
  1028. static bool IsSingleBuild (VirtualPath vp, bool recursive)
  1029. {
  1030. if (String.Compare (vp.AppRelative, "~/global.asax", StringComparison.OrdinalIgnoreCase) == 0)
  1031. return true;
  1032. if (!BatchMode)
  1033. return true;
  1034. return recursive;
  1035. }
  1036. static void LoadAssembly (string path, List <Assembly> al)
  1037. {
  1038. AddAssembly (Assembly.LoadFrom (path), al);
  1039. }
  1040. static void LoadAssembly (AssemblyInfo info, List <Assembly> al)
  1041. {
  1042. AddAssembly (Assembly.Load (info.Assembly), al);
  1043. }
  1044. static void LoadVirtualPathsToIgnore ()
  1045. {
  1046. NameValueCollection appSettings = WebConfigurationManager.AppSettings;
  1047. if (appSettings == null)
  1048. return;
  1049. string pathsFromConfig = appSettings ["MonoAspnetBatchCompileIgnorePaths"];
  1050. string pathsFromFile = appSettings ["MonoAspnetBatchCompileIgnoreFromFile"];
  1051. if (!String.IsNullOrEmpty (pathsFromConfig)) {
  1052. string[] paths = pathsFromConfig.Split (virtualPathsToIgnoreSplitChars);
  1053. string path;
  1054. foreach (string p in paths) {
  1055. path = p.Trim ();
  1056. if (path.Length == 0)
  1057. continue;
  1058. AddPathToIgnore (path);
  1059. }
  1060. }
  1061. if (!String.IsNullOrEmpty (pathsFromFile)) {
  1062. string realpath;
  1063. HttpContext ctx = HttpContext.Current;
  1064. HttpRequest req = ctx != null ? ctx.Request : null;
  1065. if (req == null)
  1066. throw new HttpException ("Missing context, cannot continue.");
  1067. realpath = req.MapPath (pathsFromFile);
  1068. if (!File.Exists (realpath))
  1069. return;
  1070. string[] paths = File.ReadAllLines (realpath);
  1071. if (paths == null || paths.Length == 0)
  1072. return;
  1073. string path;
  1074. foreach (string p in paths) {
  1075. path = p.Trim ();
  1076. if (path.Length == 0)
  1077. continue;
  1078. AddPathToIgnore (path);
  1079. }
  1080. }
  1081. }
  1082. static void OnEntryRemoved (string vp)
  1083. {
  1084. BuildManagerRemoveEntryEventHandler eh = events [buildManagerRemoveEntryEvent] as BuildManagerRemoveEntryEventHandler;
  1085. if (eh != null)
  1086. eh (new BuildManagerRemoveEntryEventArgs (vp, HttpContext.Current));
  1087. }
  1088. static void OnVirtualPathChanged (string key, object value, CacheItemRemovedReason removedReason)
  1089. {
  1090. string virtualPath;
  1091. if (StrUtils.StartsWith (key, BUILD_MANAGER_VIRTUAL_PATH_CACHE_PREFIX))
  1092. virtualPath = key.Substring (BUILD_MANAGER_VIRTUAL_PATH_CACHE_PREFIX_LENGTH);
  1093. else
  1094. return;
  1095. bool locked = false;
  1096. try {
  1097. #if SYSTEMCORE_DEP
  1098. buildCacheLock.EnterWriteLock ();
  1099. #else
  1100. buildCacheLock.AcquireWriterLock (-1);
  1101. #endif
  1102. locked = true;
  1103. if (HasCachedItemNoLock (virtualPath)) {
  1104. buildCache [virtualPath] = null;
  1105. OnEntryRemoved (virtualPath);
  1106. }
  1107. } finally {
  1108. if (locked) {
  1109. #if SYSTEMCORE_DEP
  1110. buildCacheLock.ExitWriteLock ();
  1111. #else
  1112. buildCacheLock.ReleaseWriterLock ();
  1113. #endif
  1114. }
  1115. }
  1116. }
  1117. static void ReferenceAssemblyInCompilation (BuildManagerCacheItem bmci)
  1118. {
  1119. if (recursionDepth == 0 || referencedAssemblies.Contains (bmci.BuiltAssembly))
  1120. return;
  1121. referencedAssemblies.Add (bmci.BuiltAssembly);
  1122. }
  1123. static void RemoveFailedAssemblies (string requestedVirtualPath, CompilationException ex, AssemblyBuilder abuilder,
  1124. BuildProviderGroup group, CompilerResults results, bool debug)
  1125. {
  1126. StringBuilder sb;
  1127. string newline;
  1128. if (debug) {
  1129. newline = Environment.NewLine;
  1130. sb = new StringBuilder ("Compilation of certain files in a batch failed. Another attempt to compile the batch will be made." + newline);
  1131. sb.Append ("Since you're running in debug mode, here's some more information about the error:" + newline);
  1132. } else {
  1133. newline = null;
  1134. sb = null;
  1135. }
  1136. var failedBuildProviders = new List <BuildProvider> ();
  1137. BuildProvider bp;
  1138. HttpContext ctx = HttpContext.Current;
  1139. HttpRequest req = ctx != null ? ctx.Request : null;
  1140. bool rethrow = false;
  1141. foreach (CompilerError error in results.Errors) {
  1142. if (error.IsWarning)
  1143. continue;
  1144. bp = abuilder.GetBuildProviderForPhysicalFilePath (error.FileName);
  1145. if (bp == null) {
  1146. bp = FindBuildProviderForPhysicalPath (error.FileName, group, req);
  1147. if (bp == null)
  1148. continue;
  1149. }
  1150. if (String.Compare (bp.VirtualPath, requestedVirtualPath, StringComparison.Ordinal) == 0)
  1151. rethrow = true;
  1152. if (!failedBuildProviders.Contains (bp)) {
  1153. failedBuildProviders.Add (bp);
  1154. if (sb != null)
  1155. sb.AppendFormat ("\t{0}{1}", bp.VirtualPath, newline);
  1156. }
  1157. if (sb != null)
  1158. sb.AppendFormat ("\t\t{0}{1}", error, newline);
  1159. }
  1160. foreach (BuildProvider fbp in failedBuildProviders)
  1161. group.Remove (fbp);
  1162. if (sb != null) {
  1163. sb.AppendFormat ("{0}The following exception has been thrown for the file(s) listed above:{0}{1}",
  1164. newline, ex.ToString ());
  1165. ShowDebugModeMessage (sb.ToString ());
  1166. sb = null;
  1167. }
  1168. if (rethrow)
  1169. throw new HttpException ("Compilation failed.", ex);
  1170. }
  1171. static void SetCommonParameters (CompilationSection config, CompilerParameters p, Type compilerType, string language)
  1172. {
  1173. p.IncludeDebugInformation = config.Debug;
  1174. MonoSettingsSection mss = WebConfigurationManager.GetSection ("system.web/monoSettings") as MonoSettingsSection;
  1175. if (mss == null || !mss.UseCompilersCompatibility)
  1176. return;
  1177. Compiler compiler = mss.CompilersCompatibility.Get (language);
  1178. if (compiler == null)
  1179. return;
  1180. Type type = HttpApplication.LoadType (compiler.Type, false);
  1181. if (type != compilerType)
  1182. return;
  1183. p.CompilerOptions = String.Concat (p.CompilerOptions, " ", compiler.CompilerOptions);
  1184. }
  1185. static void ShowDebugModeMessage (string msg)
  1186. {
  1187. if (suppressDebugModeMessages)
  1188. return;
  1189. Console.WriteLine ();
  1190. Console.WriteLine ("******* DEBUG MODE MESSAGE *******");
  1191. Console.WriteLine (msg);
  1192. Console.WriteLine ("******* DEBUG MODE MESSAGE *******");
  1193. Console.WriteLine ();
  1194. }
  1195. static void StoreInCache (BuildProvider bp, Assembly compiledAssembly, CompilerResults results)
  1196. {
  1197. string virtualPath = bp.VirtualPath;
  1198. var item = new BuildManagerCacheItem (compiledAssembly, bp, results);
  1199. if (buildCache.ContainsKey (virtualPath))
  1200. buildCache [virtualPath] = item;
  1201. else
  1202. buildCache.Add (virtualPath, item);
  1203. HttpContext ctx = HttpContext.Current;
  1204. HttpRequest req = ctx != null ? ctx.Request : null;
  1205. CacheDependency dep;
  1206. if (req != null) {
  1207. IDictionary <string, bool> deps = bp.ExtractDependencies ();
  1208. var files = new List <string> ();
  1209. string physicalPath;
  1210. physicalPath = req.MapPath (virtualPath);
  1211. if (File.Exists (physicalPath))
  1212. files.Add (physicalPath);
  1213. if (deps != null && deps.Count > 0) {
  1214. foreach (var d in deps) {
  1215. physicalPath = req.MapPath (d.Key);
  1216. if (!File.Exists (physicalPath))
  1217. continue;
  1218. if (!files.Contains (physicalPath))
  1219. files.Add (physicalPath);
  1220. }
  1221. }
  1222. dep = new CacheDependency (files.ToArray ());
  1223. } else
  1224. dep = null;
  1225. HttpRuntime.InternalCache.Add (BUILD_MANAGER_VIRTUAL_PATH_CACHE_PREFIX + virtualPath,
  1226. true,
  1227. dep,
  1228. Cache.NoAbsoluteExpiration,
  1229. Cache.NoSlidingExpiration,
  1230. CacheItemPriority.High,
  1231. new CacheItemRemovedCallback (OnVirtualPathChanged));
  1232. }
  1233. }
  1234. }