You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

794 lines
21 KiB

26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP version 4.0 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.02 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.php.net/license/2_02.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Sam Ruby (rubys@us.ibm.com) |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. /*
  20. * This module implements Zend OO syntax overloading support for Java
  21. * components using JNI and reflection.
  22. */
  23. #include "php.h"
  24. #include "zend_compile.h"
  25. #include "php_ini.h"
  26. #include "php_globals.h"
  27. #ifdef PHP_WIN32
  28. #include "win32/winutil.h"
  29. #define DL_ERROR php_win_err()
  30. #else
  31. #define DL_ERROR dlerror()
  32. #endif
  33. #include <jni.h>
  34. #include <stdio.h>
  35. #define IS_EXCEPTION 86
  36. /***************************************************************************/
  37. #ifndef KAFFE
  38. #ifndef JNI_11
  39. #ifndef JNI_12
  40. #ifdef JNI_VERSION_1_2
  41. #define JNI_12
  42. #else
  43. #define JNI_11
  44. #endif
  45. #endif
  46. #endif
  47. #endif
  48. #ifdef PHP_WIN32
  49. #ifdef JNI_12
  50. #define JAVALIB "jvm.dll"
  51. #else
  52. #define JAVALIB "javai.dll"
  53. #endif
  54. #else
  55. #endif
  56. /***************************************************************************/
  57. static int le_jobject = 0;
  58. static char *classpath = 0;
  59. static char *libpath = 0;
  60. static char *javahome = 0;
  61. static char *javalib = 0;
  62. static int iniUpdated = 0;
  63. static void *dl_handle = 0;
  64. typedef struct {
  65. JavaVM *jvm;
  66. JNIEnv *jenv;
  67. jobject php_reflect;
  68. jclass reflect_class;
  69. } php_java_globals;
  70. #ifdef ZTS
  71. #define JG(v) (java_globals->v)
  72. #define JG_FETCH() php_java_globals *java_globals = ts_resource(java_globals_id)
  73. #define JG_D php_java_globals *java_globals
  74. #define JG_DC , JG_D
  75. #define JG_C java_globals
  76. #define JG_CC , JG_C
  77. int java_globals_id;
  78. #else
  79. #define JG(v) (java_globals.v)
  80. #define JG_FETCH()
  81. #define JG_D
  82. #define JG_DC
  83. #define JG_C
  84. #define JG_CC
  85. php_java_globals java_globals;
  86. #endif
  87. static zend_class_entry java_class_entry;
  88. static PHP_INI_MH(OnIniUpdate) {
  89. if (new_value) *(char**)mh_arg1 = new_value;
  90. iniUpdated=1;
  91. return SUCCESS;
  92. }
  93. PHP_INI_BEGIN()
  94. PHP_INI_ENTRY1("java.class.path",
  95. NULL, PHP_INI_ALL, OnIniUpdate, &classpath)
  96. #ifndef JNI_11
  97. PHP_INI_ENTRY1("java.home",
  98. NULL, PHP_INI_ALL, OnIniUpdate, &javahome)
  99. PHP_INI_ENTRY1("java.library.path",
  100. NULL, PHP_INI_ALL, OnIniUpdate, &libpath)
  101. #endif
  102. #ifdef JAVALIB
  103. PHP_INI_ENTRY1("java.library",
  104. JAVALIB, PHP_INI_ALL, OnIniUpdate, &javalib)
  105. #else
  106. PHP_INI_ENTRY1("java.library",
  107. NULL, PHP_INI_ALL, OnIniUpdate, &javalib)
  108. #endif
  109. PHP_INI_END()
  110. /***************************************************************************/
  111. /*
  112. * Destroy a Java Virtual Machine.
  113. */
  114. void jvm_destroy() {
  115. JG_FETCH();
  116. if (JG(php_reflect)) (*JG(jenv))->DeleteGlobalRef(JG(jenv), JG(php_reflect));
  117. if (JG(jvm)) {
  118. (*JG(jvm))->DetachCurrentThread(JG(jvm));
  119. (*JG(jvm))->DestroyJavaVM(JG(jvm));
  120. JG(jvm) = 0;
  121. }
  122. if (dl_handle) DL_UNLOAD(dl_handle);
  123. JG(php_reflect) = 0;
  124. JG(jenv) = 0;
  125. }
  126. /*
  127. * Create a Java Virtual Machine.
  128. * - class.path, home, and library.path are read out of the INI file
  129. * - appropriate (pre 1.1, JDK 1.1, and JDK 1.2) initialization is performed
  130. * - net.php.reflect class file is located
  131. */
  132. #ifdef JNI_12
  133. static void addJVMOption(JavaVMInitArgs *vm_args, char *name, char *value) {
  134. char *option = (char*) malloc(strlen(name) + strlen(value) + 1);
  135. strcpy(option, name);
  136. strcat(option, value);
  137. vm_args->options[vm_args->nOptions++].optionString = option;
  138. }
  139. #endif
  140. static int jvm_create() {
  141. int rc;
  142. jobject local_php_reflect;
  143. jthrowable error;
  144. jint (JNICALL *JNI_CreateVM)(const void*,const void*,void*);
  145. #ifndef JNI_12
  146. jint (JNICALL *JNI_DefaultArgs)(void*);
  147. #endif
  148. #ifdef JNI_11
  149. JDK1_1InitArgs vm_args;
  150. #else
  151. JavaVMInitArgs vm_args;
  152. #ifdef JNI_12
  153. JavaVMOption options[3];
  154. #endif
  155. #endif
  156. JG_FETCH();
  157. iniUpdated=0;
  158. if (javalib) {
  159. dl_handle = DL_LOAD(javalib);
  160. if (!dl_handle) {
  161. php_error(E_ERROR, "Unable to load Java Library %s, error: %s",
  162. javalib, DL_ERROR);
  163. return -1;
  164. }
  165. }
  166. #ifndef JAVALIB
  167. if (!dl_handle)
  168. JNI_CreateVM = &JNI_CreateJavaVM;
  169. else
  170. #endif
  171. JNI_CreateVM = (jint (JNICALL *)(const void*,const void*,void*))
  172. DL_FETCH_SYMBOL(dl_handle, "JNI_CreateJavaVM");
  173. if (!JNI_CreateVM) {
  174. php_error(E_ERROR, "Unable to locate CreateJavaVM function");
  175. return -1;
  176. }
  177. #ifdef JNI_12
  178. vm_args.version = JNI_VERSION_1_2;
  179. vm_args.ignoreUnrecognized = JNI_FALSE;
  180. vm_args.options = options;
  181. vm_args.nOptions = 0;
  182. if (classpath) addJVMOption(&vm_args, "-Djava.class.path=", classpath);
  183. if (javahome) addJVMOption(&vm_args, "-Djava.home=", javahome);
  184. if (libpath) addJVMOption(&vm_args, "-Djava.library.path=", libpath);
  185. #else
  186. #ifndef JAVALIB
  187. if (!dl_handle)
  188. JNI_DefaultArgs = &JNI_GetDefaultJavaVMInitArgs;
  189. else
  190. #endif
  191. JNI_DefaultArgs = (jint (JNICALL *)(void*))
  192. DL_FETCH_SYMBOL(dl_handle, "JNI_GetDefaultJavaVMInitArgs");
  193. if (!JNI_DefaultArgs) {
  194. php_error(E_ERROR, "Unable to locate GetDefaultJavaVMInitArgs function");
  195. return -1;
  196. }
  197. vm_args.version=0x00010001;
  198. (*JNI_DefaultArgs)(&vm_args);
  199. if (!classpath) classpath = "";
  200. vm_args.classpath = classpath;
  201. #ifdef KAFFE
  202. vm_args.classhome = javahome;
  203. vm_args.libraryhome = libpath;
  204. #endif
  205. #endif
  206. rc = (*JNI_CreateVM)(&JG(jvm), &JG(jenv), &vm_args);
  207. if (rc) {
  208. php_error(E_ERROR, "Unable to create Java Virtual Machine");
  209. return rc;
  210. }
  211. JG(reflect_class) = (*JG(jenv))->FindClass(JG(jenv), "net/php/reflect");
  212. error = (*JG(jenv))->ExceptionOccurred(JG(jenv));
  213. if (error) {
  214. jclass errClass;
  215. jmethodID toString;
  216. jobject errString;
  217. const char *errAsUTF;
  218. jboolean isCopy;
  219. JNIEnv *jenv = JG(jenv);
  220. (*jenv)->ExceptionClear(jenv);
  221. errClass = (*jenv)->GetObjectClass(jenv, error);
  222. toString = (*jenv)->GetMethodID(jenv, errClass, "toString",
  223. "()Ljava/lang/String;");
  224. errString = (*jenv)->CallObjectMethod(jenv, error, toString);
  225. errAsUTF = (*jenv)->GetStringUTFChars(jenv, errString, &isCopy);
  226. php_error(E_ERROR, "%s", errAsUTF);
  227. if (isCopy) (*jenv)->ReleaseStringUTFChars(jenv, error, errAsUTF);
  228. jvm_destroy();
  229. return -1;
  230. }
  231. local_php_reflect = (*JG(jenv))->AllocObject(JG(jenv), JG(reflect_class));
  232. JG(php_reflect) = (*JG(jenv))->NewGlobalRef(JG(jenv), local_php_reflect);
  233. return rc;
  234. }
  235. /***************************************************************************/
  236. static jobject _java_makeObject(pval* arg JG_DC) {
  237. JNIEnv *jenv = JG(jenv);
  238. jobject result;
  239. pval **handle;
  240. int type;
  241. jmethodID makeArg;
  242. jclass hashClass;
  243. switch (arg->type) {
  244. case IS_STRING:
  245. result=(*jenv)->NewByteArray(jenv,arg->value.str.len);
  246. (*jenv)->SetByteArrayRegion(jenv,(jbyteArray)result,0,
  247. arg->value.str.len, arg->value.str.val);
  248. break;
  249. case IS_OBJECT:
  250. zend_hash_index_find(arg->value.obj.properties, 0, (void*)&handle);
  251. result = zend_list_find((*handle)->value.lval, &type);
  252. break;
  253. case IS_BOOL:
  254. makeArg = (*jenv)->GetMethodID(jenv, JG(reflect_class), "MakeArg",
  255. "(Z)Ljava/lang/Object;");
  256. result = (*jenv)->CallObjectMethod(jenv, JG(php_reflect), makeArg,
  257. (jboolean)(arg->value.lval));
  258. break;
  259. case IS_LONG:
  260. makeArg = (*jenv)->GetMethodID(jenv, JG(reflect_class), "MakeArg",
  261. "(J)Ljava/lang/Object;");
  262. result = (*jenv)->CallObjectMethod(jenv, JG(php_reflect), makeArg,
  263. (jlong)(arg->value.lval));
  264. break;
  265. case IS_DOUBLE:
  266. makeArg = (*jenv)->GetMethodID(jenv, JG(reflect_class), "MakeArg",
  267. "(D)Ljava/lang/Object;");
  268. result = (*jenv)->CallObjectMethod(jenv, JG(php_reflect), makeArg,
  269. (jdouble)(arg->value.dval));
  270. break;
  271. case IS_ARRAY:
  272. {
  273. jobject jkey, jval;
  274. zval **value;
  275. zval key;
  276. char *string_key;
  277. ulong num_key;
  278. jobject jold;
  279. jmethodID put, init;
  280. hashClass = (*jenv)->FindClass(jenv, "java/util/Hashtable");
  281. init = (*jenv)->GetMethodID(jenv, hashClass, "<init>", "()V");
  282. result = (*jenv)->NewObject(jenv, hashClass, init);
  283. put = (*jenv)->GetMethodID(jenv, hashClass, "put",
  284. "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
  285. /* Iterate through hash */
  286. zend_hash_internal_pointer_reset(arg->value.ht);
  287. while(zend_hash_get_current_data(arg->value.ht, (void**)&value) == SUCCESS) {
  288. jval = _java_makeObject(*value JG_CC);
  289. switch (zend_hash_get_current_key(arg->value.ht, &string_key, &num_key)) {
  290. case HASH_KEY_IS_STRING:
  291. key.type = IS_STRING;
  292. key.value.str.val = string_key;
  293. key.value.str.len = strlen(string_key);
  294. jkey = _java_makeObject(&key JG_CC);
  295. efree(string_key);
  296. break;
  297. case HASH_KEY_IS_LONG:
  298. key.type = IS_LONG;
  299. key.value.lval = num_key;
  300. jkey = _java_makeObject(&key JG_CC);
  301. break;
  302. default: /* HASH_KEY_NON_EXISTANT */
  303. jkey = 0;
  304. }
  305. jold = (*jenv)->CallObjectMethod(jenv, result, put, jkey, jval);
  306. if ((*value)->type != IS_OBJECT) (*jenv)->DeleteLocalRef(jenv, jval);
  307. zend_hash_move_forward(arg->value.ht);
  308. }
  309. break;
  310. }
  311. default:
  312. result=0;
  313. }
  314. return result;
  315. }
  316. /***************************************************************************/
  317. static jobjectArray _java_makeArray(int argc, pval** argv JG_DC) {
  318. JNIEnv *jenv = JG(jenv);
  319. jclass objectClass = (*jenv)->FindClass(jenv, "java/lang/Object");
  320. jobjectArray result = (*jenv)->NewObjectArray(jenv, argc, objectClass, 0);
  321. jobject arg;
  322. int i;
  323. for (i=0; i<argc; i++) {
  324. arg = _java_makeObject(argv[i] JG_CC);
  325. (*jenv)->SetObjectArrayElement(jenv, result, i, arg);
  326. if (argv[i]->type != IS_OBJECT) (*jenv)->DeleteLocalRef(jenv, arg);
  327. }
  328. return result;
  329. }
  330. static int checkError(pval *value) {
  331. if (value->type == IS_EXCEPTION) {
  332. php_error(E_WARNING, "%s", value->value.str.val);
  333. efree(value->value.str.val);
  334. var_reset(value);
  335. return 1;
  336. };
  337. return 0;
  338. }
  339. /***************************************************************************/
  340. /*
  341. * Invoke a method on an object. If method name is "java", create a new
  342. * object instead.
  343. */
  344. void java_call_function_handler
  345. (INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
  346. {
  347. JNIEnv *jenv;
  348. pval *object = property_reference->object;
  349. zend_overloaded_element *function_name = (zend_overloaded_element *)
  350. property_reference->elements_list->tail->data;
  351. int arg_count = ZEND_NUM_ARGS();
  352. jlong result = 0;
  353. pval **arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
  354. JG_FETCH();
  355. getParametersArray(ht, arg_count, arguments);
  356. if (iniUpdated && JG(jenv)) jvm_destroy();
  357. if (!JG(jenv)) jvm_create();
  358. if (!JG(jenv)) return;
  359. jenv = JG(jenv);
  360. if (!strcmp("java",function_name->element.value.str.val)) {
  361. /* construct a Java object:
  362. First argument is the class name. Any additional arguments will
  363. be treated as constructor parameters. */
  364. jmethodID co = (*jenv)->GetMethodID(jenv, JG(reflect_class), "CreateObject",
  365. "(Ljava/lang/String;[Ljava/lang/Object;J)V");
  366. jstring className;
  367. result = (jlong)(long)object;
  368. if (ZEND_NUM_ARGS() < 1) {
  369. php_error(E_ERROR, "Missing classname in new Java() call");
  370. return;
  371. }
  372. className=(*jenv)->NewStringUTF(jenv, arguments[0]->value.str.val);
  373. (*jenv)->CallVoidMethod(jenv, JG(php_reflect), co,
  374. className, _java_makeArray(arg_count-1, arguments+1 JG_CC), result);
  375. (*jenv)->DeleteLocalRef(jenv, className);
  376. } else {
  377. pval **handle;
  378. int type;
  379. jobject obj;
  380. jstring method;
  381. /* invoke a method on the given object */
  382. jmethodID invoke = (*jenv)->GetMethodID(jenv, JG(reflect_class), "Invoke",
  383. "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;J)V");
  384. zend_hash_index_find(object->value.obj.properties, 0, (void**) &handle);
  385. obj = zend_list_find((*handle)->value.lval, &type);
  386. method = (*jenv)->NewStringUTF(jenv, function_name->element.value.str.val);
  387. result = (jlong)(long)return_value;
  388. (*jenv)->CallVoidMethod(jenv, JG(php_reflect), invoke,
  389. obj, method, _java_makeArray(arg_count, arguments JG_CC), result);
  390. (*jenv)->DeleteLocalRef(jenv, method);
  391. }
  392. efree(arguments);
  393. pval_destructor(&function_name->element);
  394. checkError((pval*)(long)result);
  395. }
  396. /***************************************************************************/
  397. PHP_FUNCTION(java_last_exception_get)
  398. {
  399. jlong result = 0;
  400. jmethodID lastEx;
  401. JG_FETCH();
  402. if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
  403. result = (jlong)(long)return_value;
  404. lastEx = (*JG(jenv))->GetMethodID(JG(jenv), JG(reflect_class),
  405. "lastException", "(J)V");
  406. (*JG(jenv))->CallVoidMethod(JG(jenv), JG(php_reflect), lastEx, result);
  407. }
  408. /***************************************************************************/
  409. PHP_FUNCTION(java_last_exception_clear)
  410. {
  411. jlong result = 0;
  412. jmethodID clearEx;
  413. JG_FETCH();
  414. if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
  415. result = (jlong)(long)return_value;
  416. clearEx = (*JG(jenv))->GetMethodID(JG(jenv), JG(reflect_class),
  417. "clearException", "()V");
  418. (*JG(jenv))->CallVoidMethod(JG(jenv), JG(php_reflect), clearEx);
  419. }
  420. /***************************************************************************/
  421. static pval _java_getset_property
  422. (zend_property_reference *property_reference, jobjectArray value)
  423. {
  424. pval presult;
  425. jlong result = 0;
  426. pval **pobject;
  427. jobject obj;
  428. int type;
  429. /* get the property name */
  430. zend_llist_element *element = property_reference->elements_list->head;
  431. zend_overloaded_element *property=(zend_overloaded_element *)element->data;
  432. jstring propName;
  433. JNIEnv *jenv;
  434. JG_FETCH();
  435. jenv = JG(jenv);
  436. propName = (*jenv)->NewStringUTF(jenv, property->element.value.str.val);
  437. /* get the object */
  438. zend_hash_index_find(property_reference->object->value.obj.properties,
  439. 0, (void **) &pobject);
  440. obj = zend_list_find((*pobject)->value.lval,&type);
  441. (pval*)(long)result = &presult;
  442. var_uninit(&presult);
  443. if (!obj || (type!=le_jobject)) {
  444. php_error(E_ERROR,
  445. "Attempt to access a Java property on a non-Java object");
  446. } else {
  447. /* invoke the method */
  448. jmethodID gsp = (*jenv)->GetMethodID(jenv, JG(reflect_class), "GetSetProp",
  449. "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;J)V");
  450. (*jenv)->CallVoidMethod
  451. (jenv, JG(php_reflect), gsp, obj, propName, value, result);
  452. }
  453. (*jenv)->DeleteLocalRef(jenv, propName);
  454. pval_destructor(&property->element);
  455. return presult;
  456. }
  457. pval java_get_property_handler
  458. (zend_property_reference *property_reference)
  459. {
  460. pval presult = _java_getset_property(property_reference, 0);
  461. checkError(&presult);
  462. return presult;
  463. }
  464. int java_set_property_handler
  465. (zend_property_reference *property_reference, pval *value)
  466. {
  467. pval presult;
  468. JG_FETCH();
  469. presult = _java_getset_property
  470. (property_reference, _java_makeArray(1, &value JG_CC));
  471. return checkError(&presult) ? FAILURE : SUCCESS;
  472. }
  473. /***************************************************************************/
  474. static void _php_java_destructor(void *jobject) {
  475. JG_FETCH();
  476. if (JG(jenv)) (*JG(jenv))->DeleteGlobalRef(JG(jenv), jobject);
  477. }
  478. #ifdef ZTS
  479. static void alloc_java_globals_ctor(php_java_globals *java_globals) {
  480. memset(java_globals, 0, sizeof(php_java_globals));
  481. }
  482. #endif
  483. PHP_MINIT_FUNCTION(java) {
  484. INIT_OVERLOADED_CLASS_ENTRY(java_class_entry, "java", NULL,
  485. java_call_function_handler,
  486. java_get_property_handler,
  487. java_set_property_handler);
  488. zend_register_internal_class(&java_class_entry);
  489. le_jobject = register_list_destructors(_php_java_destructor,NULL);
  490. REGISTER_INI_ENTRIES();
  491. if (!classpath) classpath = getenv("CLASSPATH");
  492. if (!libpath) {
  493. PLS_FETCH();
  494. libpath=PG(extension_dir);
  495. }
  496. #ifdef ZTS
  497. java_globals_id = ts_allocate_id(sizeof(php_java_globals),
  498. (ts_allocate_ctor)alloc_java_globals_ctor, NULL);
  499. #endif
  500. return SUCCESS;
  501. }
  502. PHP_MSHUTDOWN_FUNCTION(java) {
  503. JG_FETCH();
  504. UNREGISTER_INI_ENTRIES();
  505. if (JG(jvm)) jvm_destroy();
  506. return SUCCESS;
  507. }
  508. function_entry java_functions[] = {
  509. PHP_FE(java_last_exception_get, NULL)
  510. PHP_FE(java_last_exception_clear, NULL)
  511. {NULL, NULL, NULL}
  512. };
  513. static PHP_MINFO_FUNCTION(java) {
  514. DISPLAY_INI_ENTRIES();
  515. }
  516. zend_module_entry java_module_entry = {
  517. "java",
  518. java_functions,
  519. PHP_MINIT(java),
  520. PHP_MSHUTDOWN(java),
  521. NULL,
  522. NULL,
  523. PHP_MINFO(java),
  524. STANDARD_MODULE_PROPERTIES
  525. };
  526. ZEND_GET_MODULE(java)
  527. /***************************************************************************/
  528. JNIEXPORT void JNICALL Java_net_php_reflect_setResultFromString
  529. (JNIEnv *jenv, jclass self, jlong result, jbyteArray jvalue)
  530. {
  531. jboolean isCopy;
  532. jbyte *value = (*jenv)->GetByteArrayElements(jenv, jvalue, &isCopy);
  533. pval *presult = (pval*)(long)result;
  534. presult->type=IS_STRING;
  535. presult->value.str.len=(*jenv)->GetArrayLength(jenv, jvalue);
  536. presult->value.str.val=emalloc(presult->value.str.len+1);
  537. memcpy(presult->value.str.val, value, presult->value.str.len);
  538. presult->value.str.val[presult->value.str.len]=0;
  539. if (isCopy) (*jenv)->ReleaseByteArrayElements(jenv, jvalue, value, 0);
  540. }
  541. JNIEXPORT void JNICALL Java_net_php_reflect_setResultFromLong
  542. (JNIEnv *jenv, jclass self, jlong result, jlong value)
  543. {
  544. pval *presult = (pval*)(long)result;
  545. presult->type=IS_LONG;
  546. presult->value.lval=(long)value;
  547. }
  548. JNIEXPORT void JNICALL Java_net_php_reflect_setResultFromDouble
  549. (JNIEnv *jenv, jclass self, jlong result, jdouble value)
  550. {
  551. pval *presult = (pval*)(long)result;
  552. presult->type=IS_DOUBLE;
  553. presult->value.dval=value;
  554. }
  555. JNIEXPORT void JNICALL Java_net_php_reflect_setResultFromBoolean
  556. (JNIEnv *jenv, jclass self, jlong result, jboolean value)
  557. {
  558. pval *presult = (pval*)(long)result;
  559. presult->type=IS_BOOL;
  560. presult->value.lval=value;
  561. }
  562. JNIEXPORT void JNICALL Java_net_php_reflect_setResultFromObject
  563. (JNIEnv *jenv, jclass self, jlong result, jobject value)
  564. {
  565. /* wrapper the java object in a pval object */
  566. pval *presult = (pval*)(long)result;
  567. pval *handle;
  568. if (presult->type != IS_OBJECT) {
  569. presult->type=IS_OBJECT;
  570. presult->value.obj.ce=&java_class_entry;
  571. presult->value.obj.properties = (HashTable *) emalloc(sizeof(HashTable));
  572. presult->is_ref=1;
  573. presult->refcount=1;
  574. zend_hash_init(presult->value.obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
  575. };
  576. ALLOC_ZVAL(handle);
  577. handle->type = IS_LONG;
  578. handle->value.lval =
  579. zend_list_insert((*jenv)->NewGlobalRef(jenv,value), le_jobject);
  580. pval_copy_constructor(handle);
  581. INIT_PZVAL(handle);
  582. zend_hash_index_update(presult->value.obj.properties, 0,
  583. &handle, sizeof(pval *), NULL);
  584. }
  585. JNIEXPORT void JNICALL Java_net_php_reflect_setResultFromArray
  586. (JNIEnv *jenv, jclass self, jlong result)
  587. {
  588. array_init( (pval*)(long)result );
  589. }
  590. JNIEXPORT jlong JNICALL Java_net_php_reflect_nextElement
  591. (JNIEnv *jenv, jclass self, jlong array)
  592. {
  593. pval *result;
  594. pval *handle = (pval*)(long)array;
  595. ALLOC_ZVAL(result);
  596. zend_hash_next_index_insert(handle->value.ht, &result, sizeof(zval *), NULL);
  597. return (jlong)(long)result;
  598. }
  599. JNIEXPORT jlong JNICALL Java_net_php_reflect_hashIndexUpdate
  600. (JNIEnv *jenv, jclass self, jlong array, jlong key)
  601. {
  602. pval *result;
  603. pval *handle = (pval*)(long)array;
  604. ALLOC_ZVAL(result);
  605. zend_hash_index_update(handle->value.ht, (unsigned long)key,
  606. &result, sizeof(zval *), NULL);
  607. return (jlong)(long)result;
  608. }
  609. JNIEXPORT jlong JNICALL Java_net_php_reflect_hashUpdate
  610. (JNIEnv *jenv, jclass self, jlong array, jbyteArray key)
  611. {
  612. pval *result;
  613. pval pkey;
  614. pval *handle = (pval*)(long)array;
  615. ALLOC_ZVAL(result);
  616. Java_net_php_reflect_setResultFromString(jenv, self, (jlong)(long)&pkey, key);
  617. zend_hash_update(handle->value.ht, pkey.value.str.val, pkey.value.str.len+1,
  618. &result, sizeof(zval *), NULL);
  619. return (jlong)(long)result;
  620. }
  621. JNIEXPORT void JNICALL Java_net_php_reflect_setException
  622. (JNIEnv *jenv, jclass self, jlong result, jbyteArray value)
  623. {
  624. pval *presult = (pval*)(long)result;
  625. Java_net_php_reflect_setResultFromString(jenv, self, result, value);
  626. presult->type=IS_EXCEPTION;
  627. }
  628. JNIEXPORT void JNICALL Java_net_php_reflect_setEnv
  629. (JNIEnv *newJenv, jclass self)
  630. {
  631. jobject local_php_reflect;
  632. JG_FETCH();
  633. iniUpdated=0;
  634. JG(jenv)=newJenv;
  635. if (!self) self = (*JG(jenv))->FindClass(JG(jenv), "net/php/reflect");
  636. JG(reflect_class) = self;
  637. if (JG(php_reflect)) (*JG(jenv))->DeleteGlobalRef(JG(jenv), JG(php_reflect));
  638. local_php_reflect = (*JG(jenv))->AllocObject(JG(jenv), JG(reflect_class));
  639. JG(php_reflect) = (*JG(jenv))->NewGlobalRef(JG(jenv), local_php_reflect);
  640. }