/src/sys/java/fanx/util/EnvProps.java

https://bitbucket.org/bedlaczech/fan-1.0 · Java · 122 lines · 88 code · 14 blank · 20 comment · 19 complexity · 1f4c31b7e3e2e721ef2bbfbae42488c9 MD5 · raw file

  1. //
  2. // Copyright (c) 2009, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 21 Jul 09 Brian Frank Original Repo code
  7. // 28 Jan 10 Brian Frank Split out into Env helper class
  8. //
  9. package fanx.util;
  10. import java.util.HashMap;
  11. import fan.sys.*;
  12. /**
  13. * EnvProps manages caching and compilation of 'Env.props'.
  14. */
  15. public class EnvProps
  16. {
  17. public EnvProps(Env env) { this.env = env; }
  18. public synchronized Map get(Pod pod, Uri uri, Duration maxAge)
  19. {
  20. Key key = new Key(pod, uri);
  21. CachedProps cp = (CachedProps)cache.get(key);
  22. if (cp == null || Duration.nowTicks() - cp.read > maxAge.ticks)
  23. cp = refresh(key, cp);
  24. return cp.props;
  25. }
  26. private CachedProps refresh(Key key, CachedProps cp)
  27. {
  28. List files = env.findAllFiles(Uri.fromStr("etc/" + key.pod + "/" + key.uri));
  29. if (cp != null && !cp.isStale(files)) return cp;
  30. if (key.uri.isPathAbs()) throw ArgErr.make("Env.props Uri must be relative: " + key.uri);
  31. cp = new CachedProps(key, files);
  32. cache.put(key, cp);
  33. return cp;
  34. }
  35. static Map readDef(Pod pod, Uri uri)
  36. {
  37. uri = Uri.fromStr(pod.uri() + "/" + uri);
  38. fan.sys.File f = (fan.sys.File)pod.file(uri, false);
  39. Map map = Sys.emptyStrStrMap;
  40. try
  41. {
  42. if (f != null) map = (Map)f.readProps().toImmutable();
  43. }
  44. catch (Exception e)
  45. {
  46. System.out.println("ERROR: Cannot load props " + pod + "::" + uri);
  47. System.out.println(" " + e);
  48. }
  49. return map;
  50. }
  51. static Map read(Map defProps, Key key, List files)
  52. {
  53. if (files.isEmpty()) return defProps;
  54. Map acc = defProps.dup();
  55. for (int i=files.sz()-1; i>=0; --i)
  56. {
  57. InStream in = ((File)files.get(i)).in();
  58. try { acc.setAll(in.readProps()); }
  59. finally { in.close(); }
  60. }
  61. return (Map)acc.toImmutable();
  62. }
  63. //////////////////////////////////////////////////////////////////////////
  64. // Key
  65. //////////////////////////////////////////////////////////////////////////
  66. static final class Key
  67. {
  68. Key(Pod p, Uri u) { pod = p; uri = u; }
  69. public int hashCode() { return pod.hashCode() ^ uri.hashCode(); }
  70. public boolean equals(Object o) { Key x = (Key)o; return pod == x.pod && uri.equals(x.uri); }
  71. final Pod pod;
  72. final Uri uri;
  73. }
  74. //////////////////////////////////////////////////////////////////////////
  75. // CachedProps
  76. //////////////////////////////////////////////////////////////////////////
  77. static class CachedProps
  78. {
  79. CachedProps(Key key, List files)
  80. {
  81. this.files = files;
  82. this.modified = new long[files.sz()];
  83. for (int i=0; i<files.sz(); ++i)
  84. this.modified[i] = ((File)files.get(i)).modified().ticks();
  85. this.defProps = readDef(key.pod, key.uri);
  86. this.props = read(defProps, key, files);
  87. this.read = Duration.nowTicks();
  88. }
  89. boolean isStale(List x)
  90. {
  91. if (files.sz() != x.sz()) return true;
  92. for (int i=0; i<x.sz(); ++i)
  93. if (modified[i] != ((File)x.get(i)).modified().ticks())
  94. return true;
  95. return false;
  96. }
  97. long read; // Duration.nowTicks when we read
  98. List files; // list of files we read from
  99. long[] modified; // timestamps of file when we read
  100. Map defProps; // props defined in pod resource (immutable)
  101. Map props; // immutable props read
  102. }
  103. //////////////////////////////////////////////////////////////////////////
  104. // Fields
  105. //////////////////////////////////////////////////////////////////////////
  106. private final Env env;
  107. private final HashMap cache = new HashMap();
  108. }