Guest User

Untitled

a guest
May 26th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.48 KB | None | 0 0
  1. /*
  2. * Rjb - Ruby <-> Java Bridge
  3. * Copyright(c) 2004,2005,2006,2009 arton
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * $Id: load.c 105 2010-05-04 00:01:26Z arton $
  16. */
  17.  
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include "ruby.h"
  21. #include "extconf.h"
  22. #if RJB_RUBY_VERSION_CODE < 190
  23. #include "intern.h"
  24. #include "st.h"
  25. #include "util.h"
  26. #else
  27. #include "ruby/intern.h"
  28. #include "ruby/st.h"
  29. #include "ruby/util.h"
  30. #endif
  31. #include "jniwrap.h"
  32. #include "jp_co_infoseek_hp_arton_rjb_RBridge.h"
  33. #include "rjb.h"
  34.  
  35. #define JVM_TYPE "client"
  36. #define ALT_JVM_TYPE "classic"
  37.  
  38. #if defined(_WIN32) || defined(__CYGWIN__)
  39. #if defined(__CYGWIN__)
  40. #define JVMDLL "%s/jre/bin/%s/jvm.dll"
  41. #define DIRSEPARATOR '/'
  42. #else
  43. #define JVMDLL "%s\\jre\\bin\\%s\\jvm.dll"
  44. #define DIRSEPARATOR '\\'
  45. #endif
  46. #define CLASSPATH_SEP ';'
  47. #elif defined(__APPLE__) && defined(__MACH__)
  48. static char* JVMDLL = "%s/Libraries/libjvm_compat.dylib";
  49. #define DIRSEPARATOR '/'
  50. #define CLASSPATH_SEP ':'
  51. #define HOME_NAME "/Home"
  52. #define HOME_NAME_LEN strlen(HOME_NAME)
  53. #define DEFAULT_HOME "/System/Library/Frameworks/JavaVM.framework"
  54. #elif defined(_AIX)
  55. #define ARCH "ppc"
  56. #undef JVM_TYPE
  57. #define JVM_TYPE "j9vm"
  58. #elif defined(__hpux)
  59. #define JVMDLL "%s/jre/lib/%s/%s/libjvm.sl"
  60. #define ARCH "PA_RISC"
  61. #undef JVM_TYPE
  62. #define JVM_TYPE "server"
  63. #define DIRSEPARATOR '/'
  64. #define CLASSPATH_SEP ':'
  65. #else /* defined(_WIN32) || defined(__CYGWIN__) */
  66. #if defined(__sparc_v9__)
  67. #define ARCH "sparcv9"
  68. #elif defined(__sparc__)
  69. #define ARCH "sparc"
  70. #elif defined(__amd64__)
  71. #define ARCH "amd64"
  72. #undef JVM_TYPE
  73. #define JVM_TYPE "server"
  74. #elif defined(i586) || defined(__i386__)
  75. #define ARCH "i386"
  76. #endif
  77. #ifndef ARCH
  78. #include <sys/systeminfo.h>
  79. #endif
  80. #define JVMDLL "%s/jre/lib/%s/%s/libjvm.so"
  81. #define DIRSEPARATOR '/'
  82. #define CLASSPATH_SEP ':'
  83. #endif
  84.  
  85. #if defined(__APPLE__) && defined(__MACH__)
  86. static char* CREATEJVM = "JNI_CreateJavaVM";
  87. static char* GETDEFAULTJVMINITARGS = "JNI_GetDefaultJavaVMInitArgs";
  88. #else
  89. #define CREATEJVM "JNI_CreateJavaVM"
  90. #define GETDEFAULTJVMINITARGS "JNI_GetDefaultJavaVMInitArgs"
  91. #endif
  92.  
  93. typedef int (JNICALL *GETDEFAULTJAVAVMINITARGS)(void*);
  94. typedef int (JNICALL *CREATEJAVAVM)(JavaVM**, JNIEnv**, void*);
  95.  
  96.  
  97. static VALUE jvmdll = Qnil;
  98. static VALUE getdefaultjavavminitargsfunc;
  99. static VALUE createjavavmfunc;
  100.  
  101. static int open_jvm(char* libpath)
  102. {
  103. int sstat;
  104. VALUE* argv;
  105.  
  106. rb_require("dl");
  107. if (!rb_const_defined_at(rb_cObject, rb_intern("DL")))
  108. {
  109. rb_raise(rb_eRuntimeError, "Constants DL is not defined.");
  110. return 0;
  111. }
  112. argv = ALLOCA_N(VALUE, 4);
  113. *argv = rb_const_get(rb_cObject, rb_intern("DL"));
  114. *(argv + 1) = rb_intern("dlopen");
  115. *(argv + 2) = 1;
  116. *(argv + 3) = rb_str_new2(libpath);
  117. jvmdll = rb_protect(rjb_safe_funcall, (VALUE)argv, &sstat);
  118. if (sstat)
  119. {
  120. return 0;
  121. }
  122. /* get function pointers of JNI */
  123. #if RJB_RUBY_VERSION_CODE < 190
  124. getdefaultjavavminitargsfunc = rb_funcall(rb_funcall(rb_funcall(jvmdll, rb_intern("[]"), 2, rb_str_new2(GETDEFAULTJVMINITARGS), rb_str_new2("IP")), rb_intern("to_ptr"), 0), rb_intern("to_i"), 0);
  125. createjavavmfunc = rb_funcall(rb_funcall(rb_funcall(jvmdll, rb_intern("[]"), 2, rb_str_new2(CREATEJVM), rb_str_new2("IPPP")), rb_intern("to_ptr"), 0), rb_intern("to_i"), 0);
  126. #else
  127. getdefaultjavavminitargsfunc = rb_funcall(jvmdll, rb_intern("[]"), 1, rb_str_new2(GETDEFAULTJVMINITARGS));
  128. createjavavmfunc = rb_funcall(jvmdll, rb_intern("[]"), 1, rb_str_new2(CREATEJVM));
  129. #endif
  130. return 1;
  131. }
  132. /*
  133. * not completed, only valid under some circumstances.
  134. */
  135. static int load_jvm(char* jvmtype)
  136. {
  137. char* libpath;
  138. char* java_home;
  139. char* jh;
  140.  
  141. jh = getenv("JAVA_HOME");
  142. #if defined(__APPLE__) && defined(__MACH__)
  143. if (!jh)
  144. {
  145. jh = DEFAULT_HOME;
  146. }
  147. else
  148. {
  149. if (strlen(jh) > HOME_NAME_LEN
  150. && strcasecmp(jh + strlen(jh) - HOME_NAME_LEN, HOME_NAME) == 0)
  151. {
  152. char* p = ALLOCA_N(char, strlen(jh) + 8);
  153. sprintf(p, "%s/..", jh);
  154. jh = p;
  155. }
  156. }
  157. #endif
  158. if (!jh)
  159. {
  160. if (RTEST(ruby_verbose))
  161. {
  162. fprintf(stderr, "no JAVA_HOME environment\n");
  163. }
  164. return 0;
  165. }
  166. #if defined(_WIN32)
  167. if (*jh == '"' && *(jh + strlen(jh) - 1) == '"')
  168. {
  169. char* p = ALLOCA_N(char, strlen(jh) + 1);
  170. strcpy(p, jh + 1);
  171. *(p + strlen(p) - 1) = '\0';
  172. jh = p;
  173. }
  174. #endif
  175. java_home = ALLOCA_N(char, strlen(jh) + 1);
  176. strcpy(java_home, jh);
  177. if (*(java_home + strlen(jh) - 1) == DIRSEPARATOR)
  178. {
  179. *(java_home + strlen(jh) - 1) = '\0';
  180. }
  181. #if defined(_WIN32) || defined(__CYGWIN__)
  182. libpath = ALLOCA_N(char, sizeof(JVMDLL) + strlen(java_home)
  183. + strlen(jvmtype) + 1);
  184. sprintf(libpath, JVMDLL, java_home, jvmtype);
  185. #elif defined(__APPLE__) && defined(__MACH__)
  186. libpath = ALLOCA_N(char, sizeof(JVMDLL) + strlen(java_home) + 1);
  187. sprintf(libpath, JVMDLL, java_home);
  188. #else /* not Windows / MAC OS-X */
  189. libpath = ALLOCA_N(char, sizeof(JVMDLL) + strlen(java_home)
  190. + strlen(ARCH) + strlen(jvmtype) + 1);
  191. sprintf(libpath, JVMDLL, java_home, ARCH, jvmtype);
  192. #endif
  193. return open_jvm(libpath);
  194. }
  195.  
  196. static int load_bridge(JNIEnv* jenv)
  197. {
  198. JNINativeMethod nmethod[1];
  199. jbyte buff[8192];
  200. char* bridge;
  201. int len;
  202. FILE* f;
  203. jclass loader = (*jenv)->FindClass(jenv, "java/lang/ClassLoader");
  204. jmethodID getSysLoader = (*jenv)->GetStaticMethodID(jenv, loader,
  205. "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
  206. jobject iloader = (*jenv)->CallStaticObjectMethod(jenv, loader, getSysLoader);
  207. VALUE v = rb_const_get_at(rb_const_get(rb_cObject, rb_intern("RjbConf")),
  208. rb_intern("BRIDGE_FILE"));
  209. bridge = StringValuePtr(v);
  210. #if defined(DOSISH)
  211. bridge = ALLOCA_N(char, strlen(bridge) + 8);
  212. strcpy(bridge, StringValuePtr(v));
  213. for (len = 0; bridge[len]; len++)
  214. {
  215. if (bridge[len] == '/')
  216. {
  217. bridge[len] = '\\';
  218. }
  219. }
  220. #endif
  221. f = fopen(bridge, "rb");
  222. if (f == NULL)
  223. {
  224. return -1;
  225. }
  226. len = fread(buff, 1, sizeof(buff), f);
  227. fclose(f);
  228. rjb_rbridge = (*jenv)->DefineClass(jenv,
  229. "jp/co/infoseek/hp/arton/rjb/RBridge", iloader, buff, len);
  230. if (rjb_rbridge == NULL)
  231. {
  232. rjb_check_exception(jenv, 1);
  233. }
  234. rjb_register_bridge = (*jenv)->GetMethodID(jenv, rjb_rbridge, "register",
  235. "(Ljava/lang/Class;)Ljava/lang/Object;");
  236. nmethod[0].name = "call";
  237. nmethod[0].signature = "(Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;";
  238. nmethod[0].fnPtr = Java_jp_co_infoseek_hp_arton_rjb_RBridge_call;
  239. (*jenv)->RegisterNatives(jenv, rjb_rbridge, nmethod, 1);
  240. rjb_rbridge = (*jenv)->NewGlobalRef(jenv, rjb_rbridge);
  241. return 0;
  242. }
  243.  
  244. int rjb_create_jvm(JNIEnv** pjenv, JavaVMInitArgs* vm_args, char* userpath, VALUE argv)
  245. {
  246. static JavaVMOption soptions[] = {
  247. #if defined(__sparc_v9__) || defined(__sparc__)
  248. { "-Xusealtsigs", NULL },
  249. #elif defined(linux) || defined(__linux__)
  250. { "-Xrs", NULL },
  251. #elif defined(__APPLE__) && defined(_ARCH_PPC)
  252. { "-Xrs", NULL },
  253. #endif
  254. #if defined(SHOW_JAVAGC)
  255. { "-verbose:gc", NULL },
  256. #endif
  257. { "DUMMY", NULL }, /* for classpath count */
  258. };
  259. char* newpath;
  260. int len;
  261. int result;
  262. GETDEFAULTJAVAVMINITARGS initargs;
  263. CREATEJAVAVM createjavavm;
  264. JavaVMOption* options;
  265. int optlen;
  266. int i;
  267. VALUE optval;
  268.  
  269. if (!RTEST(jvmdll))
  270. {
  271. char* libjvm = getenv("JVM_LIB");
  272. #if defined(_WIN32)
  273. if (libjvm && *libjvm == '"' && *(libjvm + strlen(libjvm) - 1) == '"')
  274. {
  275. char* p = ALLOCA_N(char, strlen(libjvm) + 1);
  276. strcpy(p, libjvm + 1);
  277. *(p + strlen(p) - 1) = '\0';
  278. libjvm = p;
  279. }
  280. #endif
  281. if (libjvm == NULL || !open_jvm(libjvm))
  282. {
  283. #if defined(__APPLE__) && defined(__MACH__)
  284. if (!(load_jvm(JVM_TYPE) || load_jvm(ALT_JVM_TYPE)))
  285. {
  286. JVMDLL = "%s/Libraries/libjvm.dylib";
  287. CREATEJVM = "JNI_CreateJavaVM_Impl";
  288. GETDEFAULTJVMINITARGS = "JNI_GetDefaultJavaVMInitArgs_Impl";
  289. #endif
  290. if (!(load_jvm(JVM_TYPE) || load_jvm(ALT_JVM_TYPE)))
  291. {
  292. return -1;
  293. }
  294. #if defined(__APPLE__) && defined(__MACH__)
  295. }
  296. #endif
  297. }
  298.  
  299. #if RJB_RUBY_VERSION_CODE < 190 && !defined(RUBINIUS)
  300. ruby_errinfo = Qnil;
  301. #else
  302. rb_set_errinfo(Qnil);
  303. #endif
  304. }
  305.  
  306. if (NIL_P(getdefaultjavavminitargsfunc))
  307. {
  308. return -1;
  309. }
  310. initargs = (GETDEFAULTJAVAVMINITARGS)NUM2ULONG(getdefaultjavavminitargsfunc);
  311. result = initargs(vm_args);
  312. if (0 > result)
  313. {
  314. return result;
  315. }
  316. len = strlen(userpath);
  317. if (getenv("CLASSPATH"))
  318. {
  319. len += strlen(getenv("CLASSPATH"));
  320. }
  321. newpath = ALLOCA_N(char, len + 32);
  322. if (getenv("CLASSPATH"))
  323. {
  324. sprintf(newpath, "-Djava.class.path=%s%c%s",
  325. userpath, CLASSPATH_SEP, getenv("CLASSPATH"));
  326. }
  327. else
  328. {
  329. sprintf(newpath, "-Djava.class.path=%s", userpath);
  330. }
  331. optlen = 0;
  332. if (!NIL_P(argv))
  333. {
  334. optlen += RARRAY_LEN(argv);
  335. }
  336. optlen += COUNTOF(soptions);
  337. options = ALLOCA_N(JavaVMOption, optlen);
  338. options->optionString = newpath;
  339. options->extraInfo = NULL;
  340. for (i = 1; i < COUNTOF(soptions); i++)
  341. {
  342. *(options + i) = soptions[i - 1];
  343. }
  344. for (; i < optlen; i++)
  345. {
  346. optval = rb_ary_entry(argv, i - COUNTOF(soptions));
  347. Check_Type(optval, T_STRING);
  348. (options + i)->optionString = StringValueCStr(optval);
  349. (options + i)->extraInfo = NULL;
  350. }
  351. vm_args->nOptions = optlen;
  352. vm_args->options = options;
  353. vm_args->ignoreUnrecognized = JNI_TRUE;
  354. if (NIL_P(createjavavmfunc))
  355. {
  356. return -1;
  357. }
  358. createjavavm = (CREATEJAVAVM)NUM2ULONG(createjavavmfunc);
  359. result = createjavavm(&rjb_jvm, pjenv, vm_args);
  360. if (!result)
  361. {
  362. result = load_bridge(*pjenv);
  363. if (RTEST(ruby_verbose) && result < 0)
  364. {
  365. fprintf(stderr, "failed to load the bridge class\n");
  366. }
  367. }
  368. return result;
  369. }
Add Comment
Please, Sign In to add comment