PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/sys/dotnet/fanx/util/EnvScripts.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 160 lines | 97 code | 27 blank | 36 comment | 24 complexity | ae23caca54efccae177cb95f28f31618 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2008, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 17 Mar 08 Andy Frank Creation
  7. //
  8. using System.Collections;
  9. using System.Text;
  10. using Fan.Sys;
  11. namespace Fanx.Util
  12. {
  13. /// <summary>
  14. /// ScriptUtil manages script caching and compilation.
  15. /// </summary>
  16. public class EnvScripts
  17. {
  18. //////////////////////////////////////////////////////////////////////////
  19. // Public
  20. //////////////////////////////////////////////////////////////////////////
  21. public Type compile(File file, Map options)
  22. {
  23. // normalize the file path as our cache key
  24. file = file.normalize();
  25. // unless force=true, check the cache
  26. if (!getOption(options, m_strForce, false))
  27. {
  28. CachedScript c = getCache(file);
  29. // if cached, try to lookup type (it might have been GCed)
  30. if (c != null)
  31. {
  32. Type t1 = Type.find(c.typeName, false);
  33. if (t1 != null) return t1;
  34. }
  35. }
  36. // generate a unique pod name
  37. string podName = generatePodName(file);
  38. // compile the script
  39. Pod pod = compile(podName, file, options);
  40. // get the primary type
  41. List types = pod.types();
  42. Type t = null;
  43. for (int i=0; i<types.sz(); ++i)
  44. {
  45. t = (Type)types.get(i);
  46. if (t.isPublic()) break;
  47. }
  48. if (t == null)
  49. throw Err.make("Script file defines no public classes: " + file).val;
  50. // put it into the cache
  51. putCache(file, t);
  52. return t;
  53. }
  54. //////////////////////////////////////////////////////////////////////////
  55. // Utils
  56. //////////////////////////////////////////////////////////////////////////
  57. private string generatePodName(File f)
  58. {
  59. string bse = f.basename();
  60. StringBuilder s = new StringBuilder(bse.Length+6);
  61. for (int i=0; i<bse.Length; ++i)
  62. {
  63. int c = bse[i];
  64. if ('a' <= c && c <= 'z') { s.Append((char)c); continue; }
  65. if ('A' <= c && c <= 'Z') { s.Append((char)c); continue; }
  66. if (i > 0 && '0' <= c && c <= '9') { s.Append((char)c); continue; }
  67. }
  68. lock (m_counterLock) { s.Append('_').Append(m_counter++); }
  69. return s.ToString();
  70. }
  71. private Pod compile(string podName, File f, Map options)
  72. {
  73. // use Fantom reflection to run compiler::Main.compileScript(File)
  74. Method m = Slot.findMethod("compiler::Main.compileScript", true);
  75. return (Pod)m.call(podName, f, options);
  76. }
  77. //////////////////////////////////////////////////////////////////////////
  78. // CachedScript
  79. //////////////////////////////////////////////////////////////////////////
  80. CachedScript getCache(File file)
  81. {
  82. lock (m_cache)
  83. {
  84. // check cache
  85. string key = cacheKey(file);
  86. CachedScript c = (CachedScript)m_cache[key];
  87. if (c == null) return null;
  88. // check that timestamp and size still the same
  89. if (OpUtil.compareEQ(c.modified, file.modified()) &&
  90. OpUtil.compareEQ(c.size, file.size()))
  91. return c;
  92. // nuke from cache
  93. m_cache.Remove(key);
  94. return null;
  95. }
  96. }
  97. void putCache(File file, Type t)
  98. {
  99. CachedScript c = new CachedScript();
  100. c.modified = file.modified();
  101. c.size = file.size();
  102. c.typeName = t.qname();
  103. lock (m_cache) { m_cache[cacheKey(file)] = c; }
  104. }
  105. string cacheKey(File f)
  106. {
  107. return f.toStr();
  108. }
  109. class CachedScript
  110. {
  111. public DateTime modified;
  112. public Long size;
  113. public string typeName;
  114. }
  115. //////////////////////////////////////////////////////////////////////////
  116. // Option Utils
  117. //////////////////////////////////////////////////////////////////////////
  118. bool getOption(Map options, string key, bool def)
  119. {
  120. if (options == null) return def;
  121. Boolean x = (Boolean)options.get(key);
  122. if (x == null) return def;
  123. return x.booleanValue();
  124. }
  125. //////////////////////////////////////////////////////////////////////////
  126. // Fields
  127. //////////////////////////////////////////////////////////////////////////
  128. Hashtable m_cache = new Hashtable(300);
  129. string m_strForce = "force";
  130. object m_counterLock = new object();
  131. int m_counter = 0;
  132. }
  133. }