PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/src/sys/java/fan/sys/Env.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 386 lines | 222 code | 76 blank | 88 comment | 41 complexity | 6bb4c82acfca0d90f6a949bfb4011bd6 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2010, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 27 Jan 10 Brian Frank Creation
  7. //
  8. package fan.sys;
  9. import java.util.HashMap;
  10. import fanx.util.*;
  11. /**
  12. * Env
  13. */
  14. public abstract class Env
  15. extends FanObj
  16. {
  17. static { Sys.boot(); }
  18. //////////////////////////////////////////////////////////////////////////
  19. // Construction
  20. //////////////////////////////////////////////////////////////////////////
  21. public static Env cur() { return Sys.curEnv; }
  22. public static void make$(Env self) { make$(self, cur()); }
  23. public static void make$(Env self, Env parent) { self.parent = parent; }
  24. public Env() {}
  25. public Env(Env parent) { this.parent = parent; }
  26. //////////////////////////////////////////////////////////////////////////
  27. // Obj
  28. //////////////////////////////////////////////////////////////////////////
  29. public Type typeof() { return Sys.EnvType; }
  30. public String toStr() { return typeof().toString(); }
  31. //////////////////////////////////////////////////////////////////////////
  32. // Non-Virtuals
  33. //////////////////////////////////////////////////////////////////////////
  34. public final Env parent() { return parent; }
  35. public final String os() { return Sys.os; }
  36. public final String arch() { return Sys.arch; }
  37. public final String platform() { return Sys.platform; }
  38. public final String runtime() { return "java"; }
  39. public final long idHash(Object obj) { return System.identityHashCode(obj); }
  40. //////////////////////////////////////////////////////////////////////////
  41. // Virtuals
  42. //////////////////////////////////////////////////////////////////////////
  43. public List args() { return parent.args(); }
  44. public Map vars() { return parent.vars(); }
  45. public Map diagnostics() { return parent.diagnostics(); }
  46. public void gc() { parent.gc(); }
  47. public String host() { return parent.host(); }
  48. public String user() { return parent.user(); }
  49. public InStream in() { return parent.in(); }
  50. public OutStream out() { return parent.out(); }
  51. public OutStream err() { return parent.err(); }
  52. public String promptPassword() { return this.promptPassword(""); }
  53. public String promptPassword(String msg) { return parent.promptPassword(msg); }
  54. public File homeDir() { return parent.homeDir(); }
  55. public File workDir() { return parent.workDir(); }
  56. public File tempDir() { return parent.tempDir(); }
  57. public void exit() { this.exit(0); }
  58. public void exit(long status) { parent.exit(status); }
  59. public void addShutdownHook(Func f) { parent.addShutdownHook(f); }
  60. public boolean removeShutdownHook(Func f) { return parent.removeShutdownHook(f); }
  61. //////////////////////////////////////////////////////////////////////////
  62. // Resolution
  63. //////////////////////////////////////////////////////////////////////////
  64. public File findFile(Uri uri) { return findFile(uri, true); }
  65. public File findFile(Uri uri, boolean checked)
  66. {
  67. return parent.findFile(uri, checked);
  68. }
  69. public List findAllFiles(Uri uri)
  70. {
  71. return parent.findAllFiles(uri);
  72. }
  73. public File findPodFile(String name)
  74. {
  75. return findFile(Uri.fromStr("lib/fan/" + name + ".pod"), false);
  76. }
  77. public List findAllPodNames()
  78. {
  79. List acc = new List(Sys.StrType);
  80. List files = findFile(Uri.fromStr("lib/fan/")).list();
  81. for (int i=0; i<files.sz(); ++i)
  82. {
  83. File f = (File)files.get(i);
  84. if (f.isDir() || !"pod".equals(f.ext())) continue;
  85. acc.add(f.basename());
  86. }
  87. return acc;
  88. }
  89. //////////////////////////////////////////////////////////////////////////
  90. // State
  91. //////////////////////////////////////////////////////////////////////////
  92. public Type compileScript(File file) { return compileScript(file, null); }
  93. public Type compileScript(File file, Map options)
  94. {
  95. return scripts.compile(file, options);
  96. }
  97. public List index(String key)
  98. {
  99. return index.get(key);
  100. }
  101. public List indexKeys()
  102. {
  103. return index.keys();
  104. }
  105. public Map props(Pod pod, Uri uri, Duration maxAge)
  106. {
  107. return props.get(pod, uri, maxAge);
  108. }
  109. public String config(Pod pod, String key) { return config(pod, key, null); }
  110. public String config(Pod pod, String key, String def)
  111. {
  112. return (String)props.get(pod, configProps, Duration.oneMin).get(key, def);
  113. }
  114. public String locale(Pod pod, String key) { return locale(pod, key, noDef, Locale.cur()); }
  115. public String locale(Pod pod, String key, String def) { return locale(pod, key, def, Locale.cur()); }
  116. public String locale(Pod pod, String key, String def, Locale locale)
  117. {
  118. Object val;
  119. Duration maxAge = Duration.maxVal;
  120. // 1. 'props(pod, `locale/{locale}.props`)'
  121. val = props(pod, locale.strProps, maxAge).get(key, null);
  122. if (val != null) return (String)val;
  123. // 2. 'props(pod, `locale/{lang}.props`)'
  124. val = props(pod, locale.langProps, maxAge).get(key, null);
  125. if (val != null) return (String)val;
  126. // 3. 'props(pod, `locale/en.props`)'
  127. val = props(pod, localeEnProps, maxAge).get(key, null);
  128. if (val != null) return (String)val;
  129. // 4. Fallback to 'pod::key' unless 'def' specified
  130. if (def == noDef) return pod + "::" + key;
  131. return def;
  132. }
  133. //////////////////////////////////////////////////////////////////////////
  134. // Java Env
  135. //////////////////////////////////////////////////////////////////////////
  136. /**
  137. * Load the Java class representation of Pod constants.
  138. * Default implementation delegates to parent.
  139. */
  140. public Class loadPodClass(Pod pod)
  141. {
  142. return parent.loadPodClass(pod);
  143. }
  144. /**
  145. * Load the Java class representations of a Fantom type:
  146. * - Fantom class => [class]
  147. * - Fantom mixin => [interface, body class]
  148. * - Fantom Err class => [class, val class]
  149. * Default implementation delegates to parent.
  150. */
  151. public Class[] loadTypeClasses(ClassType t)
  152. {
  153. return parent.loadTypeClasses(t);
  154. }
  155. /**
  156. * Load the Java class of a FFI JavaType.
  157. * Default implementation delegates to parent.
  158. */
  159. public Class loadJavaClass(String className)
  160. throws Exception
  161. {
  162. return parent.loadJavaClass(className);
  163. }
  164. /**
  165. * Given a Java class, get its FFI JavaType mapping. This
  166. * method is called by FanUtil.toFanType. JavaTypes are be
  167. * cached by classname once loaded.
  168. */
  169. public final JavaType loadJavaType(Class cls)
  170. {
  171. // at this point we shouldn't have any native fan type
  172. String clsName = cls.getName();
  173. if (clsName.startsWith("fan.")) throw new IllegalStateException(clsName);
  174. // cache all the java types statically
  175. synchronized (javaTypeCache)
  176. {
  177. // if cached use that one
  178. JavaType t = (JavaType)javaTypeCache.get(clsName);
  179. if (t != null) return t;
  180. // create a new one
  181. t = new JavaType(cls);
  182. javaTypeCache.put(clsName, t);
  183. return t;
  184. }
  185. }
  186. /**
  187. * Given a Java FFI qname (pod and type name), get its FFI JavaType
  188. * mapping. JavaTypes are cached once loaded. This method is
  189. * kept as light weight as possible since it is used to stub all
  190. * the FFI references at pod load time (avoid loading classes).
  191. * The JavaType will delegate to `loadJavaClass` when it is time
  192. * to load the Java class mapped by the FFI type.
  193. */
  194. public final JavaType loadJavaType(Pod loadingPod, String podName, String typeName)
  195. {
  196. // we shouldn't be using this method for pure Fantom types
  197. if (!podName.startsWith("[java]"))
  198. throw ArgErr.make("Unsupported FFI type: " + podName + "::" + typeName);
  199. // ensure unnormalized "[java] package::Type" isn't used (since
  200. // it took me an hour to track down a bug related to this)
  201. if (podName.length() >= 7 && podName.charAt(6) == ' ')
  202. throw ArgErr.make("Java FFI qname cannot contain space: " + podName + "::" + typeName);
  203. // cache all the java types statically
  204. synchronized (javaTypeCache)
  205. {
  206. // if cached use that one
  207. String clsName = JavaType.toClassName(podName, typeName);
  208. JavaType t = (JavaType)javaTypeCache.get(clsName);
  209. if (t != null) return t;
  210. // resolve class to create new JavaType for this class name
  211. try
  212. {
  213. Class cls = nameToClass(loadingPod, clsName);
  214. t = new JavaType(cls);
  215. javaTypeCache.put(clsName, t);
  216. return t;
  217. }
  218. catch (ClassNotFoundException e)
  219. {
  220. throw UnknownTypeErr.make("Load from [" + loadingPod + "] " + clsName, e);
  221. }
  222. }
  223. }
  224. /**
  225. * Return the absolute path to the JNI library for given pod.
  226. */
  227. public String jniLibPath(String podName)
  228. {
  229. String lib = workDir().osPath() + "/lib/java/ext/" + platform() + "/";
  230. String os = os();
  231. if (os == "win32") lib += podName + ".dll";
  232. else if (os == "macosx") lib += "lib" + podName + ".jnilib";
  233. else lib += "lib" + podName + ".so";
  234. // TODO FIXIT: continue to load if library not found?
  235. if (!new java.io.File(lib).exists())
  236. {
  237. System.out.println("ERR: jni library not found: " + lib);
  238. return null;
  239. }
  240. return lib;
  241. }
  242. private Class nameToClass(Pod loadingPod, String name)
  243. throws ClassNotFoundException
  244. {
  245. // first try primitives because Class.forName doesn't work for them
  246. Class cls = (Class)primitiveClasses.get(name);
  247. if (cls != null) return cls;
  248. // array class like "[I" or "[Lfoo.Bar;"
  249. if (name.charAt(0) == '[')
  250. {
  251. // if not a array of class, then use Class.forName
  252. if (!name.endsWith(";")) return Class.forName(name);
  253. // resolve component class "[Lfoo.Bar;"
  254. String compName = name.substring(2, name.length()-1);
  255. Class comp = nameToClass(loadingPod, compName);
  256. return java.lang.reflect.Array.newInstance(comp, 0).getClass();
  257. }
  258. // if we have a pod class loader use it
  259. if (loadingPod != null) return loadingPod.classLoader.loadClass(name);
  260. // fallback to Class.forName
  261. return Class.forName(name);
  262. }
  263. // String -> Class
  264. private static final HashMap primitiveClasses = new HashMap();
  265. static
  266. {
  267. try
  268. {
  269. primitiveClasses.put("boolean", boolean.class);
  270. primitiveClasses.put("char", char.class);
  271. primitiveClasses.put("byte", byte.class);
  272. primitiveClasses.put("short", short.class);
  273. primitiveClasses.put("int", int.class);
  274. primitiveClasses.put("long", long.class);
  275. primitiveClasses.put("float", float.class);
  276. primitiveClasses.put("double", double.class);
  277. }
  278. catch (Throwable e)
  279. {
  280. e.printStackTrace();
  281. }
  282. }
  283. // TODO: temp hack to get PathEnv.path
  284. public String[] toDebugPath()
  285. {
  286. Field f = typeof().field("path", false);
  287. if (f == null) return null;
  288. List list = (List)f.get(this);
  289. String[] result = new String[list.sz()];
  290. for (int i=0; i<list.sz(); ++i)
  291. {
  292. String s = ((File)list.get(i)).osPath();
  293. if (i == 0) s += " (work)";
  294. if (i == list.sz()-1) s += " (home)";
  295. result[i] = s;
  296. }
  297. return result;
  298. }
  299. //////////////////////////////////////////////////////////////////////////
  300. // Fields
  301. //////////////////////////////////////////////////////////////////////////
  302. static final String noDef = "_Env_nodef_";
  303. static Uri configProps = Uri.fromStr("config.props");
  304. static Uri localeEnProps = Uri.fromStr("locale/en.props");
  305. private Env parent;
  306. private EnvScripts scripts = new EnvScripts();
  307. private EnvProps props = new EnvProps(this);
  308. private EnvIndex index = new EnvIndex(this);
  309. private HashMap javaTypeCache = new HashMap(); // String class name => JavaType
  310. }