rjb 1.4.7-x86-mswin32-100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/riconv.c ADDED
@@ -0,0 +1,218 @@
1
+ /*
2
+ * Rjb - Ruby <-> Java Bridge
3
+ * Copyright(c) 2004 Kuwashima
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: riconv.c 117 2010-06-04 12:16:25Z arton $
16
+ */
17
+
18
+ #include "ruby.h"
19
+ #include "extconf.h"
20
+
21
+ #if defined _WIN32 || defined __CYGWIN__
22
+ #include <windows.h>
23
+ #endif
24
+
25
+ #if defined HAVE_NL_LANGINFO
26
+ #include <langinfo.h>
27
+ static const char* const NL_EUC_TABLE[] = { "EUC-JISX0213", "EUC-JP", "EUC-JP-MS" };
28
+ static const char* const NL_SJIS_TABLE[] = { "SHIFT_JIS", "SHIFT_JISX0213", "WINDOWS-31J" };
29
+ #endif
30
+
31
+ #if defined HAVE_SETLOCALE
32
+ #include <locale.h>
33
+ #endif
34
+ static const char* const LOCALE_EUC_TABLE[] = { "japanese", "ja_JP.eucJP", "japanese.euc", "ja_JP", "ja_JP.ujis" };
35
+ static const char* const LOCALE_SJIS_TABLE[] = { "japanese.sjis", "ja_JP.SJIS" };
36
+ static const char* const LOCALE_UTF8_TABLE[] = { "ja_JP.UTF-8", "ja_JP.utf8" };
37
+
38
+ #include "riconv.h"
39
+
40
+ static const char* const CS_EUCJP = "EUC-JP";
41
+ static const char* const CS_CP932 = "CP932";
42
+ static const char* const CS_SJIS = "SHIFT_JIS";
43
+ static const char* const CS_UTF8 = "UTF-8";
44
+
45
+
46
+ #if RJB_RUBY_VERSION_CODE < 190
47
+ static VALUE objIconvJ2R;
48
+ static VALUE objIconvR2J;
49
+ static const char* charcode; //is this necessary?
50
+ static char Kcode = '\0';
51
+
52
+ static int find_table(const char* const str, const char* const table[])
53
+ {
54
+ int i;
55
+ int size = sizeof(table) / sizeof(table[0]);
56
+ for (i = 0; i < size; ++i)
57
+ {
58
+ if (strstr(str, table[i])) return 1;
59
+ }
60
+ return 0;
61
+ }
62
+ #endif
63
+
64
+ #if RJB_RUBY_VERSION_CODE < 190
65
+ static const char* get_charcode_name_by_locale(const char* const name)
66
+ {
67
+ if (find_table(name, LOCALE_UTF8_TABLE))
68
+ return NULL;
69
+ else if (find_table(name, LOCALE_EUC_TABLE))
70
+ return CS_EUCJP;
71
+ else if (find_table(name, LOCALE_SJIS_TABLE))
72
+ return CS_SJIS;
73
+ else
74
+ return NULL;
75
+ }
76
+ /*
77
+ * Get better charcode name.
78
+ */
79
+ static const char* get_charcode_name()
80
+ {
81
+ const char* result = NULL;
82
+ const char* lang = NULL;
83
+
84
+ switch(Kcode)
85
+ {
86
+ case 'E':
87
+ result = CS_EUCJP;
88
+ break;
89
+ case 'S':
90
+ #if defined _WIN32 || defined __CYGWIN__
91
+ result = CS_CP932;
92
+ #else
93
+ result = CS_SJIS;
94
+ #endif
95
+ break;
96
+ case 'U':
97
+ //as is.
98
+ break;
99
+ case 'N':
100
+ default:
101
+ #if defined _WIN32 || defined __CYGWIN__
102
+ if (932 == GetACP()) result = CS_CP932;
103
+ #elif defined HAVE_NL_LANGINFO
104
+ setlocale(LC_ALL, "C"); //initialize
105
+ lang = nl_langinfo(CODESET);
106
+ if (find_table(lang, NL_EUC_TABLE))
107
+ result = CS_EUCJP;
108
+ else if (find_table(lang, NL_SJIS_TABLE))
109
+ result = CS_SJIS;
110
+ #elif defined HAVE_SETLOCALE
111
+ setlocale(LC_ALL, "C"); //initialize
112
+ result = get_charcode_name_by_locale(setlocale(LC_ALL, NULL));
113
+ #elif defined HAVE_GETENV
114
+ if (result = get_charcode_name_by_locale(getenv("LC_ALL")))
115
+ ;
116
+ else if (result = get_charcode_name_by_locale(getenv("LC_CTYPE")))
117
+ ;
118
+ else if (result = get_charcode_name_by_locale(getenv("LANG")))
119
+ ;
120
+ #endif
121
+ break;
122
+ }
123
+ return result;
124
+ }
125
+ #endif
126
+
127
+ #if RJB_RUBY_VERSION_CODE < 190
128
+ static void reinit()
129
+ {
130
+ charcode = get_charcode_name();
131
+ if (charcode)
132
+ {
133
+ VALUE rb_iconv_klass = rb_const_get(rb_cObject, rb_intern("Iconv"));
134
+ if (RTEST(rb_iconv_klass)) {
135
+ ID sym_new = rb_intern("new");
136
+ rb_gc_unregister_address(&objIconvR2J);
137
+ objIconvR2J = rb_funcall(rb_iconv_klass, sym_new, 2, rb_str_new2(CS_UTF8), rb_str_new2(charcode));
138
+ rb_gc_register_address(&objIconvR2J);
139
+ rb_gc_unregister_address(&objIconvJ2R);
140
+ objIconvJ2R = rb_funcall(rb_iconv_klass, sym_new, 2, rb_str_new2(charcode), rb_str_new2(CS_UTF8));
141
+ rb_gc_register_address(&objIconvJ2R);
142
+ }
143
+ }
144
+ else
145
+ {
146
+ objIconvR2J = objIconvJ2R = Qnil;
147
+ }
148
+ }
149
+ #endif
150
+
151
+ #if RJB_RUBY_VERSION_CODE < 190
152
+ static void check_kcode()
153
+ {
154
+ VALUE rb_iconv_klass = rb_const_get(rb_cObject, rb_intern("Iconv"));
155
+ VALUE kcode = rb_gv_get("$KCODE");
156
+ if (RTEST(rb_iconv_klass) && TYPE(kcode) == T_STRING) {
157
+ char* kcodep = StringValuePtr(kcode);
158
+ char upper_kcode = toupper(*kcodep);
159
+ if (Kcode != upper_kcode)
160
+ {
161
+ Kcode = upper_kcode;
162
+ reinit();
163
+ }
164
+ }
165
+ else
166
+ {
167
+ objIconvR2J = objIconvJ2R = Qnil;
168
+ }
169
+ }
170
+ #endif
171
+
172
+ VALUE exticonv_local_to_utf8(VALUE local_string)
173
+ {
174
+ #if RJB_RUBY_VERSION_CODE < 190
175
+ check_kcode();
176
+ if(RTEST(objIconvR2J))
177
+ {
178
+ return rb_funcall(objIconvR2J, rb_intern("iconv"), 1, local_string);
179
+ }
180
+ else
181
+ {
182
+ return local_string;
183
+ }
184
+ #else
185
+ VALUE rb_cEncoding, encoding, sjis, eucjp, iso2022jp;
186
+ rb_cEncoding = rb_const_get(rb_cObject, rb_intern("Encoding"));
187
+ sjis = rb_const_get(rb_cEncoding, rb_intern("SHIFT_JIS"));
188
+ eucjp = rb_const_get(rb_cEncoding, rb_intern("EUC_JP"));
189
+ iso2022jp = rb_const_get(rb_cEncoding, rb_intern("ISO_2022_JP"));
190
+ encoding = rb_funcall(local_string, rb_intern("encoding"), 0);
191
+
192
+ if (encoding == sjis || encoding == eucjp || encoding == iso2022jp)
193
+ {
194
+ return rb_funcall(local_string, rb_intern("encode"), 1, rb_str_new2("utf-8"));
195
+ }
196
+ else
197
+ {
198
+ return local_string;
199
+ }
200
+ #endif
201
+ }
202
+
203
+ VALUE exticonv_utf8_to_local(VALUE utf8_string)
204
+ {
205
+ #if RJB_RUBY_VERSION_CODE < 190
206
+ check_kcode();
207
+ if(RTEST(objIconvR2J))
208
+ {
209
+ return rb_funcall(objIconvJ2R, rb_intern("iconv"), 1, utf8_string);
210
+ }
211
+ else
212
+ {
213
+ return utf8_string;
214
+ }
215
+ #else
216
+ return rb_funcall(utf8_string, rb_intern("force_encoding"), 1, rb_str_new2("utf-8"));
217
+ #endif
218
+ }
data/ext/riconv.h ADDED
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Rjb - Ruby <-> Java Bridge
3
+ * Copyright(c) 2004 Kuwashima
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: riconv.h 43 2007-12-26 18:55:04Z kuwa1 $
16
+ */
17
+ #ifndef _RICONV_H
18
+ #define _RICONV_H
19
+
20
+
21
+ VALUE exticonv_local_to_utf8(VALUE);
22
+ VALUE exticonv_utf8_to_local(VALUE);
23
+
24
+ #endif /* _RICONV_H */
data/ext/rjb.c ADDED
@@ -0,0 +1,3314 @@
1
+ /*
2
+ * Rjb - Ruby <-> Java Bridge
3
+ * Copyright(c) 2004,2005,2006,2007,2008,2009,2010,2011,2012 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: rjb.c 199 2012-12-17 13:31:18Z arton $
16
+ */
17
+
18
+ #define RJB_VERSION "1.4.7"
19
+
20
+ #include "ruby.h"
21
+ #include "extconf.h"
22
+ #if RJB_RUBY_VERSION_CODE < 190
23
+ #include "st.h"
24
+ #else
25
+ #include "ruby/st.h"
26
+ #endif
27
+ #include "jniwrap.h"
28
+ #include "jp_co_infoseek_hp_arton_rjb_RBridge.h"
29
+ #include "riconv.h"
30
+ #include "rjb.h"
31
+ #include "ctype.h"
32
+
33
+ /*
34
+ * Method Modifier Flag defined in
35
+ * http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#88358
36
+ */
37
+ #define ACC_PUBLIC 0x0001
38
+ #define ACC_PRIVATE 0x0002
39
+ #define ACC_PROTECTED 0x0004
40
+ #define ACC_STATIC 0x0008
41
+ #define ACC_FINAL 0x0010
42
+ #define ACC_VOLATILE 0x0040
43
+ #define ACC_TRANSIENT 0x0080
44
+
45
+ #define RJB_FIND_CLASS(var, name) \
46
+ var = rjb_find_class_by_name(jenv, name); \
47
+ rjb_check_exception(jenv, 1)
48
+ #define RJB_HOLD_CLASS(var, name) \
49
+ var = rjb_find_class_by_name(jenv, name); \
50
+ rjb_check_exception(jenv, 1); \
51
+ var = (*jenv)->NewGlobalRef(jenv, var)
52
+ #define RJB_LOAD_METHOD(var, obj, name, sig) \
53
+ var = (*jenv)->GetMethodID(jenv, obj, name, sig); \
54
+ rjb_check_exception(jenv, 1)
55
+ #define RJB_LOAD_STATIC_METHOD(var, obj, name, sig) \
56
+ var = (*jenv)->GetStaticMethodID(jenv, obj, name, sig); \
57
+ rjb_check_exception(jenv, 1)
58
+ #if defined(RUBINIUS)
59
+ #define CLASS_NEW(obj, name) rb_define_class_under(rjb, name, obj)
60
+ #define CLASS_INHERITED(spr, kls) RTEST(rb_funcall(spr, rb_intern(">="), 1, kls))
61
+ #else
62
+ #define CLASS_NEW(obj, name) rb_define_class_under(rjb, name, obj)
63
+ #define CLASS_INHERITED(spr, kls) RTEST(rb_funcall(spr, rb_intern(">="), 1, kls))
64
+ #endif
65
+ #define IS_RJB_OBJECT(v) (CLASS_INHERITED(rjbi, rb_obj_class(v)) || rb_obj_class(v) == rjb || CLASS_INHERITED(rjbb, rb_obj_class(v)))
66
+ #define USER_INITIALIZE "@user_initialize"
67
+
68
+ static void register_class(VALUE, VALUE);
69
+ static VALUE import_class(JNIEnv* jenv, jclass, VALUE);
70
+ static VALUE register_instance(JNIEnv* jenv, VALUE klass, struct jv_data*, jobject);
71
+ static VALUE rjb_s_free(struct jv_data*);
72
+ static VALUE rjb_class_forname(int argc, VALUE* argv, VALUE self);
73
+ static void setup_metadata(JNIEnv* jenv, VALUE self, struct jv_data*, VALUE classname);
74
+ static VALUE jarray2rv(JNIEnv* jenv, jvalue val);
75
+ static jarray r2objarray(JNIEnv* jenv, VALUE v, const char* cls);
76
+ static VALUE jv2rv_withprim(JNIEnv* jenv, jobject o);
77
+ static J2R get_arrayconv(const char* cname, char* depth);
78
+ static jarray r2barray(JNIEnv* jenv, VALUE v, const char* cls);
79
+ static VALUE rjb_s_bind(VALUE self, VALUE rbobj, VALUE itfname);
80
+
81
+ static VALUE rjb;
82
+ static VALUE jklass;
83
+ static VALUE rjbc;
84
+ static VALUE rjbi;
85
+ static VALUE rjbb;
86
+ static VALUE rjba;
87
+
88
+ static ID user_initialize;
89
+ static ID initialize_proxy;
90
+ static ID cvar_classpath;
91
+ static ID anonymousblock;
92
+ static ID id_call;
93
+
94
+ VALUE rjb_loaded_classes;
95
+ static VALUE proxies;
96
+ JavaVM* rjb_jvm;
97
+ jclass rjb_rbridge;
98
+ jmethodID rjb_register_bridge;
99
+ jmethodID rjb_load_class;
100
+ static JNIEnv* main_jenv;
101
+ static VALUE primitive_conversion = Qfalse;
102
+
103
+ /*
104
+ * Object cache, never destroyed
105
+ */
106
+ /* method */
107
+ static jmethodID method_getModifiers;
108
+ static jmethodID method_getName;
109
+ static jmethodID getParameterTypes;
110
+ static jmethodID getReturnType;
111
+ /* field */
112
+ static jmethodID field_getModifiers;
113
+ static jmethodID field_getName;
114
+ static jmethodID field_getType;
115
+ /* constructor */
116
+ static jmethodID ctrGetParameterTypes;
117
+ /* class */
118
+ static jclass j_class;
119
+ jmethodID rjb_class_getName;
120
+ /* throwable */
121
+ jclass rjb_j_throwable;
122
+ jmethodID rjb_throwable_getMessage;
123
+ /* String global reference */
124
+ static jclass j_string;
125
+ static jmethodID str_tostring;
126
+ /* Object global reference */
127
+ static jclass j_object;
128
+ /* ClassLoader */
129
+ static jclass j_classloader;
130
+ static jmethodID get_system_classloader;
131
+ /* URLClassLoader */
132
+ static jclass j_url_loader;
133
+ static jobject url_loader;
134
+ static jmethodID url_loader_new;
135
+ static jmethodID url_geturls;
136
+ static jmethodID url_add_url;
137
+ /* URL global reference */
138
+ static jclass j_url;
139
+ static jmethodID url_new;
140
+
141
+ enum PrimitiveType {
142
+ PRM_INT = 0,
143
+ PRM_LONG,
144
+ PRM_DOUBLE,
145
+ PRM_BOOLEAN,
146
+ PRM_CHARACTER,
147
+ PRM_SHORT,
148
+ PRM_BYTE,
149
+ PRM_FLOAT,
150
+ /* */
151
+ PRM_LAST
152
+ };
153
+
154
+ /*
155
+ * Native type conversion table
156
+ */
157
+ typedef struct jobject_ruby_table {
158
+ const char* classname;
159
+ const char* to_prim_method;
160
+ const char* prmsig;
161
+ const char* ctrsig;
162
+ jclass klass; /* primitive class */
163
+ jmethodID to_prim_id;
164
+ jmethodID ctr_id;
165
+ J2R func;
166
+ } jprimitive_table;
167
+
168
+ JNIEnv* rjb_attach_current_thread(void)
169
+ {
170
+ JNIEnv* env;
171
+ if (!rjb_jvm) return NULL;
172
+ (*rjb_jvm)->AttachCurrentThread(rjb_jvm, (void**)&env, '\0');
173
+ return env;
174
+ }
175
+
176
+ void rjb_release_string(JNIEnv *jenv, jstring str, const char* chrs)
177
+ {
178
+ (*jenv)->ReleaseStringUTFChars(jenv, str, chrs);
179
+ (*jenv)->DeleteLocalRef(jenv, str);
180
+ }
181
+
182
+ static char* java2jniname(char* jnicls)
183
+ {
184
+ char* p;
185
+ for (p = jnicls; *p; p++)
186
+ {
187
+ if (*p == '.')
188
+ {
189
+ *p = '/';
190
+ }
191
+ }
192
+ return jnicls;
193
+ }
194
+
195
+ static char* jniname2java(char* jniname)
196
+ {
197
+ char* p;
198
+ for (p = jniname; *p; p++)
199
+ {
200
+ if (*p == '/')
201
+ {
202
+ *p = '.';
203
+ }
204
+ }
205
+ return jniname;
206
+ }
207
+
208
+ static char* next_sig(char* p)
209
+ {
210
+ if (!*p)
211
+ {
212
+ return p;
213
+ }
214
+ if (*p == '[')
215
+ {
216
+ p++;
217
+ }
218
+ if (*p == 'L')
219
+ {
220
+ while (*p && *p != ';')
221
+ {
222
+ p++;
223
+ }
224
+ }
225
+ return (*p) ? ++p : p;
226
+ }
227
+
228
+ static VALUE jstring2val(JNIEnv* jenv, jstring s)
229
+ {
230
+ const char* p;
231
+ VALUE v;
232
+
233
+ if (s == NULL)
234
+ {
235
+ return Qnil;
236
+ }
237
+ p = (*jenv)->GetStringUTFChars(jenv, s, NULL);
238
+ v = rb_str_new2(p);
239
+ v = exticonv_utf8_to_local(v);
240
+ rjb_release_string(jenv, s, p);
241
+ return v;
242
+ }
243
+
244
+ /*
245
+ * Type conversion tables
246
+ */
247
+ typedef struct type_conversion_table {
248
+ const char* jtype;
249
+ const char* jntype;
250
+ R2J r2j;
251
+ J2R j2r;
252
+ J2R ja2r;
253
+ R2JARRAY r2ja;
254
+ off_t jcall; /* for instance method */
255
+ off_t jscall; /* for static method */
256
+ } jconv_table;
257
+
258
+ /*
259
+ * conversion methods
260
+ * val will be released in this function.
261
+ */
262
+ static VALUE jv2rclass(JNIEnv* jenv, jclass jc)
263
+ {
264
+ const char* cname;
265
+ VALUE clsname;
266
+ VALUE v;
267
+ jstring nm = (*jenv)->CallObjectMethod(jenv, jc, rjb_class_getName);
268
+ rjb_check_exception(jenv, 0);
269
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
270
+ clsname = rb_str_new2(cname);
271
+ rjb_release_string(jenv, nm, cname);
272
+ v = rb_hash_aref(rjb_loaded_classes, clsname);
273
+ if (v == Qnil)
274
+ {
275
+ v = import_class(jenv, jc, clsname);
276
+ }
277
+ (*jenv)->DeleteLocalRef(jenv, jc);
278
+ return v;
279
+ }
280
+
281
+ static VALUE jv2rv_r(JNIEnv* jenv, jvalue val)
282
+ {
283
+ const char* cname;
284
+ jstring nm;
285
+ jclass klass;
286
+ VALUE clsname;
287
+ VALUE v;
288
+ struct jv_data* ptr;
289
+ /* object to ruby */
290
+ if (!val.l) return Qnil;
291
+ klass = (*jenv)->GetObjectClass(jenv, val.l);
292
+
293
+ if ((*jenv)->IsSameObject(jenv, klass, j_class))
294
+ {
295
+ (*jenv)->DeleteLocalRef(jenv, klass);
296
+ return jv2rclass(jenv, val.l);
297
+ }
298
+ nm = (*jenv)->CallObjectMethod(jenv, klass, rjb_class_getName);
299
+ rjb_check_exception(jenv, 0);
300
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
301
+ if (*cname == '[')
302
+ {
303
+ char depth = 0;
304
+ J2R j2r = get_arrayconv(cname, &depth);
305
+ rjb_release_string(jenv, nm, cname);
306
+ v = j2r(jenv, val);
307
+ (*jenv)->DeleteLocalRef(jenv, klass);
308
+ (*jenv)->DeleteLocalRef(jenv, val.l);
309
+ return v;
310
+ }
311
+ clsname = rb_str_new2(cname);
312
+ rjb_release_string(jenv, nm, cname);
313
+ v = rb_hash_aref(rjb_loaded_classes, clsname);
314
+ if (v == Qnil)
315
+ {
316
+ v = import_class(jenv, klass, clsname);
317
+ }
318
+ Data_Get_Struct(v, struct jv_data, ptr);
319
+ v = register_instance(jenv, v, (struct jv_data*)ptr, val.l);
320
+ (*jenv)->DeleteLocalRef(jenv, klass);
321
+ (*jenv)->DeleteLocalRef(jenv, val.l);
322
+ return v;
323
+ }
324
+
325
+ VALUE jv2rv(JNIEnv* jenv, jvalue val)
326
+ {
327
+ if (RTEST(primitive_conversion))
328
+ {
329
+ return jv2rv_withprim(jenv, val.l);
330
+ }
331
+ return jv2rv_r(jenv, val);
332
+ }
333
+
334
+ static VALUE jvoid2rv(JNIEnv* jenv, jvalue val)
335
+ {
336
+ return Qnil;
337
+ }
338
+
339
+ static VALUE jbyte2rv(JNIEnv* jenv, jvalue val)
340
+ {
341
+ return INT2NUM(val.b);
342
+ }
343
+
344
+ static VALUE jchar2rv(JNIEnv* jenv, jvalue val)
345
+ {
346
+ return INT2NUM(val.c);
347
+ }
348
+
349
+ static VALUE jdouble2rv(JNIEnv* jenv, jvalue val)
350
+ {
351
+ return rb_float_new(val.d);
352
+ }
353
+
354
+ static VALUE jfloat2rv(JNIEnv* jenv, jvalue val)
355
+ {
356
+ return rb_float_new((double)val.f);
357
+ }
358
+
359
+ static VALUE jint2rv(JNIEnv* jenv, jvalue val)
360
+ {
361
+ return INT2NUM(val.i);
362
+ }
363
+
364
+ static VALUE jlong2rv(JNIEnv* jenv, jvalue val)
365
+ {
366
+ #if HAVE_LONG_LONG
367
+ return LL2NUM(val.j);
368
+ #else
369
+ char bignum[64];
370
+ sprintf(bignum, "%ld * 0x100000000 + 0x%lx",
371
+ (long)(val.j >> 32), (unsigned long)val.j);
372
+ return rb_eval_string(bignum);
373
+ #endif
374
+ }
375
+
376
+ static VALUE jshort2rv(JNIEnv* jenv, jvalue val)
377
+ {
378
+ return INT2NUM(val.s);
379
+ }
380
+
381
+ static VALUE jboolean2rv(JNIEnv* jenv, jvalue val)
382
+ {
383
+ return (val.z) ? Qtrue : Qfalse;
384
+ }
385
+
386
+ static VALUE jstring2rv(JNIEnv* jenv, jvalue val)
387
+ {
388
+ return jstring2val(jenv, (jstring)val.l);
389
+ }
390
+
391
+ static VALUE ja2r(J2R conv, JNIEnv* jenv, jvalue val, int depth)
392
+ {
393
+ jsize len;
394
+ VALUE v;
395
+ int i;
396
+ if (!val.l) return Qnil;
397
+ if (depth == 1)
398
+ {
399
+ return conv(jenv, val);
400
+ }
401
+ len = (*jenv)->GetArrayLength(jenv, val.l);
402
+ v = rb_ary_new2(len);
403
+ for (i = 0; i < len; i++)
404
+ {
405
+ jvalue wrap;
406
+ wrap.l = (*jenv)->GetObjectArrayElement(jenv, val.l, i);
407
+ rb_ary_push(v, ja2r(conv, jenv, wrap, depth - 1));
408
+ }
409
+ (*jenv)->DeleteLocalRef(jenv, val.l);
410
+ return v;
411
+ }
412
+
413
+ static VALUE jarray2rv(JNIEnv* jenv, jvalue val)
414
+ {
415
+ jsize len;
416
+ VALUE v;
417
+ int i;
418
+ if (!val.l) return Qnil;
419
+ len = (*jenv)->GetArrayLength(jenv, val.l);
420
+ v = rb_ary_new2(len);
421
+ for (i = 0; i < len; i++)
422
+ {
423
+ jvalue wrap;
424
+ wrap.l = (*jenv)->GetObjectArrayElement(jenv, val.l, i);
425
+ /* wrap.l will be release in jv2rv */
426
+ rb_ary_push(v, jv2rv(jenv, wrap));
427
+ }
428
+ (*jenv)->DeleteLocalRef(jenv, val.l);
429
+ return v;
430
+ }
431
+
432
+ static VALUE ca2rv(JNIEnv* jenv, void* p)
433
+ {
434
+ return INT2FIX(*(jchar*)p);
435
+ }
436
+
437
+ static VALUE da2rv(JNIEnv* jenv, void* p)
438
+ {
439
+ return rb_float_new(*(jdouble*)p);
440
+ }
441
+
442
+ static VALUE fa2rv(JNIEnv* jenv, void* p)
443
+ {
444
+ return rb_float_new(*(jfloat*)p);
445
+ }
446
+
447
+ static VALUE ia2rv(JNIEnv* jenv, void* p)
448
+ {
449
+ return INT2NUM(*(jint*)p);
450
+ }
451
+
452
+ static VALUE la2rv(JNIEnv* jenv, void* p)
453
+ {
454
+ #if HAVE_LONG_LONG
455
+ return LL2NUM(*(jlong*)p);
456
+ #else
457
+ return LONG2NUM(*(jlong*)p);
458
+ #endif
459
+ }
460
+
461
+ static VALUE sa2rv(JNIEnv* jenv, void* p)
462
+ {
463
+ return INT2FIX(*(jshort*)p);
464
+ }
465
+
466
+ static VALUE ba2rv(JNIEnv* jenv, void* p)
467
+ {
468
+ return (*(jboolean*)p) ? Qtrue : Qfalse;
469
+ }
470
+
471
+ /*
472
+ * val : released in this function.
473
+ */
474
+ static VALUE call_conv(JNIEnv* jenv, jvalue val, size_t sz, void* p, CONV conv, size_t fnc)
475
+ {
476
+ int i;
477
+ char* cp = (char*)p;
478
+ jsize len = (*jenv)->GetArrayLength(jenv, val.l);
479
+ VALUE v = rb_ary_new2(len);
480
+ for (i = 0; i < len; i++)
481
+ {
482
+ rb_ary_push(v, conv(jenv, cp));
483
+ cp += sz;
484
+ }
485
+ (*(RELEASEARRAY*)(((char*)*jenv) + fnc))(jenv, val.l, p, JNI_ABORT);
486
+ (*jenv)->DeleteLocalRef(jenv, val.l);
487
+ return v;
488
+ }
489
+
490
+ static VALUE jbytearray2rv(JNIEnv* jenv, jvalue val)
491
+ {
492
+ jsize len = (*jenv)->GetArrayLength(jenv, val.l);
493
+ jbyte* p = (*jenv)->GetByteArrayElements(jenv, val.l, NULL);
494
+ VALUE v = rb_str_new((char*)p, len);
495
+ (*jenv)->ReleaseByteArrayElements(jenv, val.l, p, JNI_ABORT);
496
+ (*jenv)->DeleteLocalRef(jenv, val.l);
497
+ return v;
498
+ }
499
+ static VALUE jchararray2rv(JNIEnv* jenv, jvalue val)
500
+ {
501
+ jchar* p = (*jenv)->GetCharArrayElements(jenv, val.l, NULL);
502
+ return call_conv(jenv, val, sizeof(jchar), p, ca2rv,
503
+ offsetof(struct JNINativeInterface_, ReleaseCharArrayElements));
504
+ }
505
+ static VALUE jdoublearray2rv(JNIEnv* jenv, jvalue val)
506
+ {
507
+ jdouble* p = (*jenv)->GetDoubleArrayElements(jenv, val.l, NULL);
508
+ return call_conv(jenv, val, sizeof(jdouble), p, da2rv,
509
+ offsetof(struct JNINativeInterface_, ReleaseDoubleArrayElements));
510
+ }
511
+ static VALUE jfloatarray2rv(JNIEnv* jenv, jvalue val)
512
+ {
513
+ jfloat* p = (*jenv)->GetFloatArrayElements(jenv, val.l, NULL);
514
+ return call_conv(jenv, val, sizeof(jfloat), p, fa2rv,
515
+ offsetof(struct JNINativeInterface_, ReleaseFloatArrayElements));
516
+ }
517
+ static VALUE jintarray2rv(JNIEnv* jenv, jvalue val)
518
+ {
519
+ jint* p = (*jenv)->GetIntArrayElements(jenv, val.l, NULL);
520
+ return call_conv(jenv, val, sizeof(jint), p, ia2rv,
521
+ offsetof(struct JNINativeInterface_, ReleaseIntArrayElements));
522
+ }
523
+ static VALUE jlongarray2rv(JNIEnv* jenv, jvalue val)
524
+ {
525
+ jlong* p = (*jenv)->GetLongArrayElements(jenv, val.l, NULL);
526
+ return call_conv(jenv, val, sizeof(jlong), p, la2rv,
527
+ offsetof(struct JNINativeInterface_, ReleaseLongArrayElements));
528
+ }
529
+ static VALUE jshortarray2rv(JNIEnv* jenv, jvalue val)
530
+ {
531
+ jshort* p = (*jenv)->GetShortArrayElements(jenv, val.l, NULL);
532
+ return call_conv(jenv, val, sizeof(jshort), p, sa2rv,
533
+ offsetof(struct JNINativeInterface_, ReleaseShortArrayElements));
534
+ }
535
+ static VALUE jstringarray2rv(JNIEnv* jenv, jvalue val)
536
+ {
537
+ int i;
538
+ jsize len = (*jenv)->GetArrayLength(jenv, val.l);
539
+ VALUE v = rb_ary_new2(len);
540
+ for (i = 0; i < len; i++)
541
+ {
542
+ jobject p = (*jenv)->GetObjectArrayElement(jenv, val.l, i);
543
+ rb_ary_push(v, jstring2val(jenv, (jstring)p));
544
+ }
545
+ (*jenv)->DeleteLocalRef(jenv, val.l);
546
+ return v;
547
+ }
548
+ static VALUE jbooleanarray2rv(JNIEnv* jenv, jvalue val)
549
+ {
550
+ jboolean* p = (*jenv)->GetBooleanArrayElements(jenv, val.l, NULL);
551
+ return call_conv(jenv, val, sizeof(jboolean), p, ba2rv,
552
+ offsetof(struct JNINativeInterface_, ReleaseBooleanArrayElements));
553
+ }
554
+
555
+ /*
556
+ * table that handles java primitive type.
557
+ * index: according to enum PrimitiveType.
558
+ */
559
+ static jprimitive_table jpcvt[] = {
560
+ { "java/lang/Integer", "intValue", "()I", "(I)V", NULL, 0, 0, jint2rv, },
561
+ { "java/lang/Long", "longValue", "()J", "(J)V", NULL, 0, 0, jlong2rv, },
562
+ { "java/lang/Double", "doubleValue", "()D", "(D)V", NULL, 0, 0, jdouble2rv, },
563
+ { "java/lang/Boolean", "booleanValue", "()Z", "(Z)Ljava/lang/Boolean;",
564
+ NULL, 0, 0, jboolean2rv, },
565
+ { "java/lang/Character", "charValue", "()C", NULL, NULL, 0, 0, jchar2rv, },
566
+ { "java/lang/Short", "intValue", "()I", NULL, NULL, 0, 0, jint2rv, },
567
+ { "java/lang/Byte", "intValue", "()I", NULL, NULL, 0, 0, jint2rv, },
568
+ { "java/lang/Float", "doubleValue", "()D", NULL, NULL, 0, 0, jdouble2rv, },
569
+ };
570
+
571
+ /*
572
+ * o will be released in this function.
573
+ */
574
+ static VALUE jv2rv_withprim(JNIEnv* jenv, jobject o)
575
+ {
576
+ jvalue jv;
577
+ int i;
578
+ jclass klass;
579
+ jv.j = 0;
580
+ if (!o)
581
+ rb_raise(rb_eRuntimeError, "Object is NULL");
582
+ klass = (*jenv)->GetObjectClass(jenv, o);
583
+ for (i = PRM_INT; i < PRM_LAST; i++)
584
+ {
585
+ if ((*jenv)->IsSameObject(jenv, jpcvt[i].klass, klass))
586
+ {
587
+ switch (*(jpcvt[i].to_prim_method))
588
+ {
589
+ case 'i':
590
+ jv.i = (*jenv)->CallIntMethod(jenv, o, jpcvt[i].to_prim_id);
591
+ break;
592
+ case 'b':
593
+ jv.z = (*jenv)->CallBooleanMethod(jenv, o, jpcvt[i].to_prim_id);
594
+ break;
595
+ case 'd':
596
+ jv.d = (*jenv)->CallDoubleMethod(jenv, o, jpcvt[i].to_prim_id);
597
+ break;
598
+ case 'c':
599
+ jv.c = (*jenv)->CallCharMethod(jenv, o, jpcvt[i].to_prim_id);
600
+ break;
601
+ case 'l':
602
+ jv.j = (*jenv)->CallLongMethod(jenv, o, jpcvt[i].to_prim_id);
603
+ break;
604
+ default:
605
+ rb_raise(rb_eRuntimeError, "no convertor defined(%d)", i);
606
+ break;
607
+ }
608
+ (*jenv)->DeleteLocalRef(jenv, o);
609
+ return jpcvt[i].func(jenv, jv);
610
+ }
611
+ }
612
+ if ((*jenv)->IsSameObject(jenv, j_string, klass))
613
+ {
614
+ return jstring2val(jenv, o);
615
+ }
616
+ jv.l = o;
617
+ return jv2rv_r(jenv, jv);
618
+ }
619
+
620
+ /*
621
+ * functions convert VALUE to jvalue
622
+ */
623
+ static void rv2jv(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
624
+ {
625
+ jv->l = NULL;
626
+ }
627
+
628
+ static void rv2jbyte(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
629
+ {
630
+ if (!release)
631
+ jv->b = (jbyte)NUM2INT(val);
632
+ }
633
+ static void rv2jchar(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
634
+ {
635
+ if (!release)
636
+ jv->c = (jchar)NUM2INT(val);
637
+ }
638
+ static void rv2jdouble(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
639
+ {
640
+ if (release) return;
641
+ switch (TYPE(val))
642
+ {
643
+ case T_FIXNUM:
644
+ jv->d = NUM2INT(val);
645
+ break;
646
+ case T_FLOAT:
647
+ jv->d = NUM2DBL(val);
648
+ break;
649
+ default:
650
+ rb_raise(rb_eRuntimeError, "can't change to double");
651
+ break;
652
+ }
653
+ }
654
+ static void rv2jfloat(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
655
+ {
656
+ if (release) return;
657
+ switch (TYPE(val))
658
+ {
659
+ case T_FIXNUM:
660
+ jv->f = (float)NUM2INT(val);
661
+ break;
662
+ case T_FLOAT:
663
+ jv->f = (float)NUM2DBL(val);
664
+ break;
665
+ default:
666
+ rb_raise(rb_eRuntimeError, "can't change to float");
667
+ break;
668
+ }
669
+ }
670
+ static void rv2jint(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
671
+ {
672
+ if (!release)
673
+ jv->i = NUM2INT(val);
674
+ }
675
+ static void rv2jlong(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
676
+ {
677
+ if (release) return;
678
+ switch (TYPE(val))
679
+ {
680
+ case T_FIXNUM:
681
+ jv->j = FIX2LONG(val);
682
+ break;
683
+ default:
684
+ #if HAVE_LONG_LONG
685
+ jv->j = NUM2LL(val);
686
+ #else
687
+ rb_raise(rb_eRuntimeError, "can't change to long");
688
+ #endif
689
+ break;
690
+ }
691
+ }
692
+ static void rv2jshort(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
693
+ {
694
+ if (release) return;
695
+ if (TYPE(val) == T_FIXNUM)
696
+ {
697
+ int n = FIX2INT(val);
698
+ if (abs(n) < 0x7fff)
699
+ {
700
+ jv->s = (short)n;
701
+ return;
702
+ }
703
+ }
704
+ rb_raise(rb_eRuntimeError, "can't change to short");
705
+ }
706
+ static void rv2jboolean(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
707
+ {
708
+ if (!release)
709
+ jv->z = (RTEST(val)) ? JNI_TRUE : JNI_FALSE;
710
+ }
711
+ static void rv2jstring(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
712
+ {
713
+ if (!release)
714
+ {
715
+ if (TYPE(val) == T_DATA && IS_RJB_OBJECT(val))
716
+ {
717
+ struct jvi_data* ptr;
718
+ Data_Get_Struct(val, struct jvi_data, ptr);
719
+ if ((*jenv)->IsInstanceOf(jenv, ptr->obj, j_string))
720
+ {
721
+ jv->l = ptr->obj;
722
+ }
723
+ else
724
+ {
725
+ jmethodID tostr;
726
+ jstring js;
727
+ tostr = (*jenv)->GetMethodID(jenv, ptr->klass, "toString", "()Ljava/lang/String;");
728
+ rjb_check_exception(jenv, 0);
729
+ js = (*jenv)->CallObjectMethod(jenv, ptr->obj, tostr);
730
+ rjb_check_exception(jenv, 0);
731
+ jv->l = js;
732
+ }
733
+ }
734
+ else
735
+ {
736
+ if (NIL_P(val))
737
+ {
738
+ jv->l = NULL;
739
+ }
740
+ else
741
+ {
742
+ val = exticonv_local_to_utf8(val);
743
+ jv->l = (*jenv)->NewStringUTF(jenv, StringValuePtr(val));
744
+ }
745
+ }
746
+ }
747
+ else
748
+ {
749
+ if (TYPE(val) == T_DATA)
750
+ {
751
+ if (IS_RJB_OBJECT(val))
752
+ {
753
+ struct jvi_data* ptr;
754
+ Data_Get_Struct(val, struct jvi_data, ptr);
755
+ if ((*jenv)->IsInstanceOf(jenv, ptr->obj, j_string))
756
+ {
757
+ return; /* never delete at this time */
758
+ }
759
+ }
760
+ }
761
+ (*jenv)->DeleteLocalRef(jenv, jv->l);
762
+ }
763
+ }
764
+
765
+ /*
766
+ * psig may be NULL (from proxy/array call)
767
+ */
768
+ static void rv2jobject(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
769
+ {
770
+ if (!release)
771
+ {
772
+ jv->l = NULL;
773
+ if (val == Qtrue || val == Qfalse)
774
+ {
775
+ jv->l = (*jenv)->CallStaticObjectMethod(jenv,
776
+ jpcvt[PRM_BOOLEAN].klass, jpcvt[PRM_BOOLEAN].ctr_id,
777
+ (val == Qtrue) ? JNI_TRUE : JNI_FALSE);
778
+ }
779
+ else if (NIL_P(val))
780
+ {
781
+ /* no-op */
782
+ }
783
+ else if (FIXNUM_P(val))
784
+ {
785
+ jvalue arg;
786
+ int idx = PRM_INT;
787
+ #if HAVE_LONG_LONG
788
+ arg.j = FIX2LONG(val);
789
+ if (arg.j < INT_MIN || arg.j > INT_MAX)
790
+ {
791
+ idx = PRM_LONG;
792
+ }
793
+ #else
794
+ arg.i = FIX2LONG(val);
795
+ #endif
796
+ jv->l = (*jenv)->NewObject(jenv, jpcvt[idx].klass,
797
+ jpcvt[idx].ctr_id, arg);
798
+ }
799
+ else
800
+ {
801
+ jvalue arg;
802
+ switch (TYPE(val))
803
+ {
804
+ case T_DATA:
805
+ if (IS_RJB_OBJECT(val))
806
+ {
807
+ /* TODO: check instanceof (class (in psig) ) */
808
+ struct jvi_data* ptr;
809
+ Data_Get_Struct(val, struct jvi_data, ptr);
810
+ jv->l = ptr->obj;
811
+ }
812
+ else if (rb_obj_class(val) == rjbb)
813
+ {
814
+ struct rj_bridge* ptr;
815
+ Data_Get_Struct(val, struct rj_bridge, ptr);
816
+ jv->l = ptr->proxy;
817
+ }
818
+ else if (CLASS_INHERITED(rjbc, rb_obj_class(val)))
819
+ {
820
+ struct jv_data* ptr;
821
+ Data_Get_Struct(val, struct jv_data, ptr);
822
+ jv->l = ptr->idata.obj;
823
+ }
824
+ break;
825
+ case T_STRING:
826
+ if (psig && *psig == '[' && *(psig + 1) == 'B') {
827
+ jv->l = r2barray(jenv, val, NULL);
828
+ } else {
829
+ rv2jstring(jenv, val, jv, NULL, 0);
830
+ }
831
+ break;
832
+ case T_FLOAT:
833
+ arg.d = NUM2DBL(val);
834
+ jv->l = (*jenv)->NewObject(jenv, jpcvt[PRM_DOUBLE].klass,
835
+ jpcvt[PRM_DOUBLE].ctr_id, arg.d);
836
+ break;
837
+ case T_ARRAY:
838
+ jv->l = r2objarray(jenv, val, "Ljava/lang/Object;");
839
+ break;
840
+ #if HAVE_LONG_LONG
841
+ case T_BIGNUM:
842
+ arg.j = rb_big2ll(val);
843
+ jv->l = (*jenv)->NewObject(jenv, jpcvt[PRM_LONG].klass,
844
+ jpcvt[PRM_LONG].ctr_id, arg);
845
+ break;
846
+ #endif
847
+ case T_OBJECT:
848
+ default:
849
+ #if DEBUG
850
+ fprintf(stderr, "rtype:%d, sig=%s\n", TYPE(val), psig);
851
+ fflush(stderr);
852
+ #endif
853
+ rb_raise(rb_eRuntimeError, "can't convert to java type");
854
+ break;
855
+ }
856
+ }
857
+ }
858
+ else
859
+ {
860
+ switch (TYPE(val))
861
+ {
862
+ case T_STRING:
863
+ case T_FLOAT:
864
+ case T_ARRAY:
865
+ case T_BIGNUM:
866
+ if (jv->l) (*jenv)->DeleteLocalRef(jenv, jv->l);
867
+ break;
868
+ }
869
+ }
870
+ }
871
+
872
+ static void check_fixnumarray(VALUE v)
873
+ {
874
+ size_t i;
875
+ size_t len = RARRAY_LEN(v);
876
+ VALUE* p = RARRAY_PTR(v);
877
+ /* check all fixnum (overflow is permit) */
878
+ for (i = 0; i < len; i++)
879
+ {
880
+ if (!FIXNUM_P(*p++))
881
+ {
882
+ rb_raise(rb_eRuntimeError, "array element must be a fixnum");
883
+ }
884
+ }
885
+ }
886
+
887
+ static jarray r2barray(JNIEnv* jenv, VALUE v, const char* cls)
888
+ {
889
+ jarray ary = NULL;
890
+ if (TYPE(v) == T_STRING)
891
+ {
892
+ ary = (*jenv)->NewByteArray(jenv, (jint)RSTRING_LEN(v));
893
+ (*jenv)->SetByteArrayRegion(jenv, ary, 0, (jint)RSTRING_LEN(v),
894
+ (const jbyte*)RSTRING_PTR(v));
895
+ }
896
+ else if (TYPE(v) == T_ARRAY)
897
+ {
898
+ int i;
899
+ jbyte* pb;
900
+ check_fixnumarray(v);
901
+ ary = (*jenv)->NewByteArray(jenv, (jint)RARRAY_LEN(v));
902
+ pb = (*jenv)->GetByteArrayElements(jenv, ary, NULL);
903
+ for (i = 0; i < RARRAY_LEN(v); i++)
904
+ {
905
+ *(pb + i) = (jbyte)FIX2ULONG(RARRAY_PTR(v)[i]);
906
+ }
907
+ (*jenv)->ReleaseByteArrayElements(jenv, ary, pb, 0);
908
+ }
909
+ if (!ary)
910
+ {
911
+ rb_raise(rb_eRuntimeError, "can't coerce to byte array");
912
+ }
913
+ return ary;
914
+ }
915
+
916
+ static jarray r2carray(JNIEnv* jenv, VALUE v, const char* cls)
917
+ {
918
+ jarray ary = NULL;
919
+ if (TYPE(v) == T_ARRAY)
920
+ {
921
+ int i;
922
+ jchar* pb;
923
+ check_fixnumarray(v);
924
+ ary = (*jenv)->NewCharArray(jenv, (jint)RARRAY_LEN(v));
925
+ pb = (*jenv)->GetCharArrayElements(jenv, ary, NULL);
926
+ for (i = 0; i < RARRAY_LEN(v); i++)
927
+ {
928
+ *(pb + i) = (jchar)FIX2ULONG(RARRAY_PTR(v)[i]);
929
+ }
930
+ (*jenv)->ReleaseCharArrayElements(jenv, ary, pb, 0);
931
+ return ary;
932
+ }
933
+ rb_raise(rb_eRuntimeError, "can't coerce to char array");
934
+ }
935
+
936
+ static jarray r2darray(JNIEnv* jenv, VALUE v, const char* cls)
937
+ {
938
+ jarray ary = NULL;
939
+ if (TYPE(v) == T_ARRAY)
940
+ {
941
+ int i;
942
+ jdouble* pb;
943
+ ary = (*jenv)->NewDoubleArray(jenv, (jint)RARRAY_LEN(v));
944
+ pb = (*jenv)->GetDoubleArrayElements(jenv, ary, NULL);
945
+ for (i = 0; i < RARRAY_LEN(v); i++)
946
+ {
947
+ *(pb + i) = (jdouble)rb_num2dbl(RARRAY_PTR(v)[i]);
948
+ }
949
+ (*jenv)->ReleaseDoubleArrayElements(jenv, ary, pb, 0);
950
+ return ary;
951
+ }
952
+ rb_raise(rb_eRuntimeError, "can't coerce to double array");
953
+ }
954
+
955
+ static jarray r2farray(JNIEnv* jenv, VALUE v, const char* cls)
956
+ {
957
+ jarray ary = NULL;
958
+ if (TYPE(v) == T_ARRAY)
959
+ {
960
+ int i;
961
+ jfloat* pb;
962
+ ary = (*jenv)->NewFloatArray(jenv, (jint)RARRAY_LEN(v));
963
+ pb = (*jenv)->GetFloatArrayElements(jenv, ary, NULL);
964
+ for (i = 0; i < RARRAY_LEN(v); i++)
965
+ {
966
+ *(pb + i) = (jfloat)rb_num2dbl(RARRAY_PTR(v)[i]);
967
+ }
968
+ (*jenv)->ReleaseFloatArrayElements(jenv, ary, pb, 0);
969
+ return ary;
970
+ }
971
+ rb_raise(rb_eRuntimeError, "can't coerce to float array");
972
+ }
973
+
974
+ static jarray r2iarray(JNIEnv* jenv, VALUE v, const char* cls)
975
+ {
976
+ jarray ary = NULL;
977
+ if (TYPE(v) == T_ARRAY)
978
+ {
979
+ int i;
980
+ jint* pb;
981
+ check_fixnumarray(v);
982
+ ary = (*jenv)->NewIntArray(jenv, (jint)RARRAY_LEN(v));
983
+ pb = (*jenv)->GetIntArrayElements(jenv, ary, NULL);
984
+ for (i = 0; i < RARRAY_LEN(v); i++)
985
+ {
986
+ *(pb + i) = (jint)FIX2LONG(RARRAY_PTR(v)[i]);
987
+ }
988
+ (*jenv)->ReleaseIntArrayElements(jenv, ary, pb, 0);
989
+ return ary;
990
+ }
991
+ rb_raise(rb_eRuntimeError, "can't coerce to int array");
992
+ }
993
+
994
+ static jarray r2larray(JNIEnv* jenv, VALUE v, const char* cls)
995
+ {
996
+ jarray ary = NULL;
997
+ if (TYPE(v) == T_ARRAY)
998
+ {
999
+ int i;
1000
+ jlong* pb;
1001
+ ary = (*jenv)->NewLongArray(jenv, (jint)RARRAY_LEN(v));
1002
+ pb = (*jenv)->GetLongArrayElements(jenv, ary, NULL);
1003
+ for (i = 0; i < RARRAY_LEN(v); i++)
1004
+ {
1005
+ #if HAVE_LONG_LONG
1006
+ *(pb + i) = (jlong)rb_num2ll(RARRAY_PTR(v)[i]);
1007
+ #else
1008
+ *(pb + i) = (jlong)FIX2LONG(RARRAY_PTR(v)[i]);
1009
+ #endif
1010
+ }
1011
+ (*jenv)->ReleaseLongArrayElements(jenv, ary, pb, 0);
1012
+ return ary;
1013
+ }
1014
+ rb_raise(rb_eRuntimeError, "can't coerce to long array");
1015
+ }
1016
+
1017
+ static jarray r2sarray(JNIEnv* jenv, VALUE v, const char* cls)
1018
+ {
1019
+ jarray ary = NULL;
1020
+ if (TYPE(v) == T_ARRAY)
1021
+ {
1022
+ int i;
1023
+ jshort* pb;
1024
+ check_fixnumarray(v);
1025
+ ary = (*jenv)->NewShortArray(jenv, (jint)RARRAY_LEN(v));
1026
+ pb = (*jenv)->GetShortArrayElements(jenv, ary, NULL);
1027
+ for (i = 0; i < RARRAY_LEN(v); i++)
1028
+ {
1029
+ *(pb + i) = (jshort)FIX2LONG(RARRAY_PTR(v)[i]);
1030
+ }
1031
+ (*jenv)->ReleaseShortArrayElements(jenv, ary, pb, 0);
1032
+ return ary;
1033
+ }
1034
+ rb_raise(rb_eRuntimeError, "can't coerce to short array");
1035
+ }
1036
+
1037
+ static jarray r2boolarray(JNIEnv* jenv, VALUE v, const char* cls)
1038
+ {
1039
+ jarray ary = NULL;
1040
+ if (TYPE(v) == T_ARRAY)
1041
+ {
1042
+ int i;
1043
+ jboolean* pb;
1044
+ ary = (*jenv)->NewBooleanArray(jenv, (jint)RARRAY_LEN(v));
1045
+ pb = (*jenv)->GetBooleanArrayElements(jenv, ary, NULL);
1046
+ for (i = 0; i < RARRAY_LEN(v); i++)
1047
+ {
1048
+ *(pb + i)
1049
+ = (!RTEST(RARRAY_PTR(v)[i]))
1050
+ ? JNI_FALSE : JNI_TRUE;
1051
+ }
1052
+ (*jenv)->ReleaseBooleanArrayElements(jenv, ary, pb, 0);
1053
+ return ary;
1054
+ }
1055
+ rb_raise(rb_eRuntimeError, "can't coerce to boolean array");
1056
+ }
1057
+
1058
+ static jarray r2voidarray(JNIEnv* jenv, VALUE v, const char* cls)
1059
+ {
1060
+ rb_raise(rb_eRuntimeError, "void never arrayed");
1061
+ }
1062
+
1063
+ static jarray r2objarray(JNIEnv* jenv, VALUE v, const char* cls)
1064
+ {
1065
+ jarray ary = NULL;
1066
+ if (TYPE(v) == T_ARRAY)
1067
+ {
1068
+ int i;
1069
+ ary = (*jenv)->NewObjectArray(jenv, (jint)RARRAY_LEN(v), j_object, NULL);
1070
+ rjb_check_exception(jenv, 0);
1071
+ for (i = 0; i < RARRAY_LEN(v); i++)
1072
+ {
1073
+ jvalue jv;
1074
+ rv2jobject(jenv, RARRAY_PTR(v)[i], &jv, NULL, 0);
1075
+ (*jenv)->SetObjectArrayElement(jenv, ary, i, jv.l);
1076
+ }
1077
+ return ary;
1078
+ }
1079
+ rb_raise(rb_eRuntimeError, "can't coerce to object array");
1080
+ }
1081
+
1082
+ /*
1083
+ * Type convertion tables
1084
+ */
1085
+ static const jconv_table jcvt[] = {
1086
+ { "byte", "B", rv2jbyte, jbyte2rv,
1087
+ jbytearray2rv, r2barray,
1088
+ offsetof(struct JNINativeInterface_, CallByteMethodA),
1089
+ offsetof(struct JNINativeInterface_, CallStaticByteMethodA), },
1090
+ { "char", "C", rv2jchar, jchar2rv,
1091
+ jchararray2rv, r2carray,
1092
+ offsetof(struct JNINativeInterface_, CallCharMethodA),
1093
+ offsetof(struct JNINativeInterface_, CallStaticCharMethodA), },
1094
+ { "double", "D", rv2jdouble, jdouble2rv,
1095
+ jdoublearray2rv, r2darray,
1096
+ offsetof(struct JNINativeInterface_, CallDoubleMethodA),
1097
+ offsetof(struct JNINativeInterface_, CallStaticDoubleMethodA), },
1098
+ { "float", "F", rv2jfloat, jfloat2rv,
1099
+ jfloatarray2rv, r2farray,
1100
+ offsetof(struct JNINativeInterface_, CallFloatMethodA),
1101
+ offsetof(struct JNINativeInterface_, CallStaticFloatMethodA), },
1102
+ { "int", "I", rv2jint, jint2rv,
1103
+ jintarray2rv, r2iarray,
1104
+ offsetof(struct JNINativeInterface_, CallIntMethodA),
1105
+ offsetof(struct JNINativeInterface_, CallStaticIntMethodA), },
1106
+ { "long", "J", rv2jlong, jlong2rv,
1107
+ jlongarray2rv, r2larray,
1108
+ offsetof(struct JNINativeInterface_, CallLongMethodA),
1109
+ offsetof(struct JNINativeInterface_, CallStaticLongMethodA), },
1110
+ { "short", "S", rv2jshort, jshort2rv,
1111
+ jshortarray2rv, r2sarray,
1112
+ offsetof(struct JNINativeInterface_, CallShortMethodA),
1113
+ offsetof(struct JNINativeInterface_, CallStaticShortMethodA), },
1114
+ { "boolean", "Z", rv2jboolean, jboolean2rv,
1115
+ jbooleanarray2rv, r2boolarray,
1116
+ offsetof(struct JNINativeInterface_, CallBooleanMethodA),
1117
+ offsetof(struct JNINativeInterface_, CallStaticBooleanMethodA), },
1118
+ { "void", "V", rv2jv, jvoid2rv,
1119
+ NULL, r2voidarray,
1120
+ offsetof(struct JNINativeInterface_, CallVoidMethodA),
1121
+ offsetof(struct JNINativeInterface_, CallStaticVoidMethodA), },
1122
+ { "java.lang.String", "Ljava.lang.String;", rv2jstring, jstring2rv,
1123
+ jstringarray2rv, r2objarray,
1124
+ offsetof(struct JNINativeInterface_, CallObjectMethodA),
1125
+ offsetof(struct JNINativeInterface_, CallStaticObjectMethodA), },
1126
+ };
1127
+
1128
+ static void rv2jarray(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
1129
+ {
1130
+ if (*psig != '[')
1131
+ {
1132
+ rb_raise(rb_eRuntimeError, "argument signature not array");
1133
+ }
1134
+ if (release)
1135
+ {
1136
+ if (TYPE(val) == T_STRING && *(psig + 1) == 'B')
1137
+ {
1138
+ // copy array's contents into arg string
1139
+ jsize len = (*jenv)->GetArrayLength(jenv, jv->l);
1140
+ jbyte* p = (*jenv)->GetByteArrayElements(jenv, jv->l, NULL);
1141
+ if (len <= RSTRING_LEN(val))
1142
+ {
1143
+ memcpy(StringValuePtr(val), p, len);
1144
+ }
1145
+ else
1146
+ {
1147
+ VALUE src = rb_str_new((char*)p, len);
1148
+ rb_str_set_len(val, 0);
1149
+ rb_str_append(val, src);
1150
+ }
1151
+ }
1152
+ (*jenv)->DeleteLocalRef(jenv, jv->l);
1153
+ }
1154
+ else
1155
+ {
1156
+ jint i;
1157
+ jarray ja = NULL;
1158
+ if (NIL_P(val))
1159
+ {
1160
+ /* no-op, null for an array */
1161
+ }
1162
+ else if (*(psig + 1) == '[')
1163
+ {
1164
+ if (TYPE(val) != T_ARRAY) {
1165
+ rb_raise(rb_eRuntimeError, "array's rank unmatch");
1166
+ }
1167
+ ja = (*jenv)->NewObjectArray(jenv, (jint)RARRAY_LEN(val), j_object, NULL);
1168
+ rjb_check_exception(jenv, 0);
1169
+ for (i = 0; i < (jint)RARRAY_LEN(val); i++)
1170
+ {
1171
+ jvalue jv;
1172
+ rv2jarray(jenv, RARRAY_PTR(val)[i], &jv, psig + 1, 0);
1173
+ (*jenv)->SetObjectArrayElement(jenv, ja, (jint)i, jv.l);
1174
+ }
1175
+ }
1176
+ else
1177
+ {
1178
+ R2JARRAY r2a = r2objarray;
1179
+ for (i = 0; i < (jint)COUNTOF(jcvt); i++)
1180
+ {
1181
+ if (*(psig + 1) == jcvt[i].jntype[0])
1182
+ {
1183
+ r2a = jcvt[i].r2ja;
1184
+ break;
1185
+ }
1186
+ }
1187
+ ja = r2a(jenv, val, psig + 1);
1188
+ }
1189
+ jv->l = ja;
1190
+ }
1191
+ }
1192
+
1193
+ /*
1194
+ */
1195
+ static R2J get_r2j(JNIEnv* jenv, jobject o, int* siglen, char* sigp)
1196
+ {
1197
+ size_t len, i;
1198
+ const char* cname;
1199
+ R2J result = NULL;
1200
+ jstring nm = (*jenv)->CallObjectMethod(jenv, o, rjb_class_getName);
1201
+ rjb_check_exception(jenv, 0);
1202
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1203
+ if (*cname == '[')
1204
+ {
1205
+ if (siglen)
1206
+ {
1207
+ len = strlen(cname);
1208
+ *siglen += (int)len;
1209
+ strcpy(sigp, cname);
1210
+ }
1211
+ result = rv2jarray;
1212
+ }
1213
+ else
1214
+ {
1215
+ for (i = 0; i < COUNTOF(jcvt); i++)
1216
+ {
1217
+ if (!strcmp(cname, jcvt[i].jtype))
1218
+ {
1219
+ if (siglen)
1220
+ {
1221
+ *siglen += (int)strlen(jcvt[i].jntype);
1222
+ strcpy(sigp, jcvt[i].jntype);
1223
+ }
1224
+ result = jcvt[i].r2j;
1225
+ break;
1226
+ }
1227
+ }
1228
+ if (!result)
1229
+ {
1230
+ if (siglen)
1231
+ {
1232
+ *siglen += sprintf(sigp, "L%s;", cname);
1233
+ }
1234
+ result = rv2jobject;
1235
+ }
1236
+ }
1237
+ rjb_release_string(jenv, nm, cname);
1238
+ return result;
1239
+ }
1240
+
1241
+ static J2R get_arrayconv(const char* cname, char* pdepth)
1242
+ {
1243
+ size_t i;
1244
+ size_t start;
1245
+ for (start = 1; *(cname + start) == '['; start++);
1246
+ *pdepth = (char)start;
1247
+ for (i = 0; i < COUNTOF(jcvt); i++)
1248
+ {
1249
+ if (*(cname + start) == jcvt[i].jntype[0])
1250
+ {
1251
+ if (jcvt[i].jntype[0] == 'L'
1252
+ && strncmp(cname + start, jcvt[i].jntype, strlen(jcvt[i].jntype)))
1253
+ {
1254
+ break;
1255
+ }
1256
+ return jcvt[i].ja2r;
1257
+ }
1258
+ }
1259
+ return &jarray2rv;
1260
+ }
1261
+
1262
+ static J2R get_j2r(JNIEnv* jenv, jobject cls, char* psig, char* pdepth, char* ppsig, off_t* piv, int static_method)
1263
+ {
1264
+ size_t i;
1265
+ J2R result = NULL;
1266
+ const char* cname;
1267
+ const char* jname = NULL;
1268
+ jstring nm = (*jenv)->CallObjectMethod(jenv, cls, rjb_class_getName);
1269
+ rjb_check_exception(jenv, 0);
1270
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1271
+
1272
+ if (*cname == '[')
1273
+ {
1274
+ result = get_arrayconv(cname, pdepth);
1275
+ jname = cname;
1276
+ }
1277
+ else
1278
+ {
1279
+ for (i = 0; i < COUNTOF(jcvt); i++)
1280
+ {
1281
+ if (!strcmp(cname, jcvt[i].jtype))
1282
+ {
1283
+ result = jcvt[i].j2r;
1284
+ *piv = (static_method) ? jcvt[i].jscall : jcvt[i].jcall;
1285
+ if (jcvt[i].jntype[0] != 'L')
1286
+ {
1287
+ *psig = jcvt[i].jntype[0];
1288
+ }
1289
+ jname = jcvt[i].jntype;
1290
+ break;
1291
+ }
1292
+ }
1293
+ }
1294
+ if (ppsig)
1295
+ {
1296
+ if (!jname)
1297
+ {
1298
+ sprintf(ppsig, "L%s;", cname);
1299
+ }
1300
+ else
1301
+ {
1302
+ strcpy(ppsig, jname);
1303
+ }
1304
+ java2jniname(ppsig);
1305
+ }
1306
+ rjb_release_string(jenv, nm, cname);
1307
+ return result;
1308
+ }
1309
+
1310
+ static void setup_j2r(JNIEnv* jenv, jobject cls, struct cls_method* pm, int static_method)
1311
+ {
1312
+ off_t iv = 0;
1313
+ J2R result = get_j2r(jenv, cls, &pm->basic.result_signature, &pm->basic.result_arraydepth, NULL, &iv, static_method);
1314
+ pm->result_convert = (result) ? result : jv2rv;
1315
+ if (iv)
1316
+ {
1317
+ pm->method = iv;
1318
+ }
1319
+ else
1320
+ {
1321
+ pm->method = (static_method)
1322
+ ? offsetof(struct JNINativeInterface_, CallStaticObjectMethodA)
1323
+ : offsetof(struct JNINativeInterface_, CallObjectMethodA);
1324
+ }
1325
+ }
1326
+
1327
+ static void fill_convert(JNIEnv* jenv, struct cls_constructor* cls, jobjectArray tp, int count)
1328
+ {
1329
+ int i, siglen;
1330
+ R2J* tbl = ALLOC_N(R2J, count);
1331
+ char** sig = (char**)ALLOCA_N(char*, count);
1332
+ char siga[256];
1333
+ cls->arg_convert = tbl;
1334
+ memset(tbl, 0, sizeof(R2J) * count);
1335
+ siglen = 0;
1336
+ for (i = 0; i < count; i++)
1337
+ {
1338
+ jobject o = (*jenv)->GetObjectArrayElement(jenv, tp, i);
1339
+ *(tbl + i) = get_r2j(jenv, o, &siglen, siga);
1340
+ *(sig + i) = ALLOCA_N(char, strlen(siga) + 1);
1341
+ strcpy(*(sig + i), siga);
1342
+ }
1343
+ cls->method_signature = ALLOC_N(char, siglen + 1);
1344
+ *(cls->method_signature) = 0;
1345
+ for (i = 0; i < count; i++)
1346
+ {
1347
+ strcat(cls->method_signature, *(sig + i));
1348
+ }
1349
+ }
1350
+
1351
+ /*
1352
+ * create method info structure
1353
+ * m = instance of Method class
1354
+ * c = instance of the class
1355
+ */
1356
+ static void setup_methodbase(JNIEnv* jenv, struct cls_constructor* pm,
1357
+ jobjectArray parama, jsize pcount)
1358
+ {
1359
+ pm->arg_count = pcount;
1360
+ pm->method_signature = NULL;
1361
+ pm->result_signature = 'O';
1362
+ pm->result_arraydepth = 0;
1363
+ pm->arg_convert = NULL;
1364
+ if (pcount)
1365
+ {
1366
+ fill_convert(jenv, pm, parama, pcount);
1367
+ }
1368
+ }
1369
+
1370
+ static void register_methodinfo(struct cls_method* newpm, st_table* tbl)
1371
+ {
1372
+ struct cls_method* pm;
1373
+
1374
+ if (st_lookup(tbl, newpm->name, (st_data_t*)&pm))
1375
+ {
1376
+ newpm->next = pm->next;
1377
+ pm->next = newpm;
1378
+ }
1379
+ else
1380
+ {
1381
+ newpm->next = NULL;
1382
+ st_insert(tbl, newpm->name, (VALUE)newpm);
1383
+ }
1384
+ }
1385
+
1386
+ static struct cls_method* clone_methodinfo(struct cls_method* pm)
1387
+ {
1388
+ struct cls_method* result = ALLOC(struct cls_method);
1389
+ memcpy(result, pm, sizeof(struct cls_method));
1390
+ return result;
1391
+ }
1392
+
1393
+ static int make_alias(const char* jname, char* rname)
1394
+ {
1395
+ int ret = 0;
1396
+ while (*jname)
1397
+ {
1398
+ if (isupper(*jname))
1399
+ {
1400
+ *rname++ = '_';
1401
+ *rname++ = tolower(*jname++);
1402
+ ret = 1;
1403
+ }
1404
+ else
1405
+ {
1406
+ *rname++ = *jname++;
1407
+ }
1408
+ }
1409
+ *rname = '\0';
1410
+ return ret;
1411
+ }
1412
+
1413
+ static void create_methodinfo(JNIEnv* jenv, st_table* tbl, jobject m, int static_method)
1414
+ {
1415
+ struct cls_method* result;
1416
+ struct cls_method* pm;
1417
+ const char* jname;
1418
+ int alias;
1419
+ jstring nm;
1420
+ jobjectArray parama;
1421
+ jobject cls;
1422
+ jsize param_count;
1423
+ char* rname;
1424
+
1425
+ result = ALLOC(struct cls_method);
1426
+ parama = (*jenv)->CallObjectMethod(jenv, m, getParameterTypes);
1427
+ rjb_check_exception(jenv, 0);
1428
+ param_count = (*jenv)->GetArrayLength(jenv, parama);
1429
+ rjb_check_exception(jenv, 0);
1430
+ setup_methodbase(jenv, &result->basic, parama, param_count);
1431
+ nm = (*jenv)->CallObjectMethod(jenv, m, method_getName);
1432
+ rjb_check_exception(jenv, 0);
1433
+ jname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1434
+ rname = ALLOCA_N(char, strlen(jname) * 2 + 8);
1435
+ alias = make_alias(jname, rname);
1436
+ result->name = rb_intern(jname);
1437
+ rjb_release_string(jenv, nm, jname);
1438
+ result->basic.id = (*jenv)->FromReflectedMethod(jenv, m);
1439
+ rjb_check_exception(jenv, 0);
1440
+ cls = (*jenv)->CallObjectMethod(jenv, m, getReturnType);
1441
+ rjb_check_exception(jenv, 0);
1442
+ setup_j2r(jenv, cls, result, static_method);
1443
+ (*jenv)->DeleteLocalRef(jenv, cls);
1444
+ result->static_method = static_method;
1445
+ register_methodinfo(result, tbl);
1446
+ /* create method alias */
1447
+ pm = NULL;
1448
+ if (strlen(rname) > 3
1449
+ && (*rname == 'g' || *rname == 's') && *(rname + 1) == 'e' && *(rname + 2) == 't')
1450
+ {
1451
+ pm = clone_methodinfo(result);
1452
+ if (*rname == 's')
1453
+ {
1454
+ if (result->basic.arg_count == 1)
1455
+ {
1456
+ rname += 3;
1457
+ strcat(rname, "=");
1458
+ }
1459
+ }
1460
+ else
1461
+ {
1462
+ rname += 3;
1463
+ }
1464
+ if (*rname == '_') rname++;
1465
+ }
1466
+ else if (strlen(rname) > 2 && result->basic.result_signature == 'Z'
1467
+ && *rname == 'i' && *(rname + 1) == 's')
1468
+ {
1469
+ pm = clone_methodinfo(result);
1470
+ rname += 2;
1471
+ if (*rname == '_') rname++;
1472
+ strcat(rname, "?");
1473
+ }
1474
+ else if (alias)
1475
+ {
1476
+ pm = clone_methodinfo(result);
1477
+ }
1478
+ if (pm)
1479
+ {
1480
+ pm->name = rb_intern(rname);
1481
+ register_methodinfo(pm, tbl);
1482
+ }
1483
+ }
1484
+
1485
+ static void create_fieldinfo(JNIEnv* jenv, st_table* tbl, jobject f, int readonly, int static_field)
1486
+ {
1487
+ struct cls_field* result;
1488
+ const char* jname;
1489
+ jstring nm;
1490
+ jobject cls;
1491
+ char sigs[256];
1492
+ off_t iv = 0;
1493
+
1494
+ result = ALLOC(struct cls_field);
1495
+ memset(result, 0, sizeof(struct cls_field));
1496
+ nm = (*jenv)->CallObjectMethod(jenv, f, field_getName);
1497
+ rjb_check_exception(jenv, 0);
1498
+ jname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1499
+ result->name = rb_intern(jname);
1500
+ rjb_release_string(jenv, nm, jname);
1501
+ result->id = (*jenv)->FromReflectedField(jenv, f);
1502
+ rjb_check_exception(jenv, 0);
1503
+ cls = (*jenv)->CallObjectMethod(jenv, f, field_getType);
1504
+ rjb_check_exception(jenv, 0);
1505
+ result->value_convert = get_j2r(jenv, cls, &result->result_signature, &result->result_arraydepth, sigs, &iv, 0);
1506
+ result->arg_convert = get_r2j(jenv, cls, NULL, NULL);
1507
+ (*jenv)->DeleteLocalRef(jenv, cls);
1508
+ result->field_signature = ALLOC_N(char, strlen(sigs) + 1);
1509
+ strcpy(result->field_signature, sigs);
1510
+ if (!result->value_convert) result->value_convert = jv2rv;
1511
+ result->readonly = readonly;
1512
+ result->static_field = static_field;
1513
+ st_insert(tbl, result->name, (VALUE)result);
1514
+ }
1515
+
1516
+ static void setup_constructors(JNIEnv* jenv, struct cls_constructor*** pptr, jobjectArray methods)
1517
+ {
1518
+ int i;
1519
+ struct cls_constructor* pc;
1520
+ jsize mcount = (*jenv)->GetArrayLength(jenv, methods);
1521
+ struct cls_constructor** tbl = ALLOC_N(struct cls_constructor*, mcount + 1);
1522
+ *pptr = tbl;
1523
+ for (i = 0; i < mcount; i++)
1524
+ {
1525
+ jobjectArray parama;
1526
+ jsize pcount;
1527
+ jobject c = (*jenv)->GetObjectArrayElement(jenv, methods, i);
1528
+ rjb_check_exception(jenv, 0);
1529
+ pc = ALLOC(struct cls_constructor);
1530
+ tbl[i] = pc;
1531
+ parama = (*jenv)->CallObjectMethod(jenv, c, ctrGetParameterTypes);
1532
+ rjb_check_exception(jenv, 0);
1533
+ pcount = (*jenv)->GetArrayLength(jenv, parama);
1534
+ rjb_check_exception(jenv, 0);
1535
+ setup_methodbase(jenv, pc, parama, pcount);
1536
+ pc->id = (*jenv)->FromReflectedMethod(jenv, c);
1537
+ (*jenv)->DeleteLocalRef(jenv, c);
1538
+ }
1539
+ tbl[mcount] = NULL;
1540
+ }
1541
+
1542
+ static void setup_methods(JNIEnv* jenv, st_table** tbl, st_table** static_tbl,
1543
+ jobjectArray methods)
1544
+ {
1545
+ int i;
1546
+ jint modifier;
1547
+ jsize mcount = (*jenv)->GetArrayLength(jenv, methods);
1548
+ *tbl = st_init_numtable_with_size(mcount);
1549
+ *static_tbl = st_init_numtable();
1550
+ for (i = 0; i < mcount; i++)
1551
+ {
1552
+ jobject m = (*jenv)->GetObjectArrayElement(jenv, methods, i);
1553
+ rjb_check_exception(jenv, 0);
1554
+ modifier = (*jenv)->CallIntMethod(jenv, m, method_getModifiers);
1555
+ if (!(modifier & ACC_STATIC))
1556
+ {
1557
+ create_methodinfo(jenv, *tbl, m, 0);
1558
+ }
1559
+ else
1560
+ {
1561
+ create_methodinfo(jenv, *static_tbl, m, 1);
1562
+ }
1563
+ (*jenv)->DeleteLocalRef(jenv, m);
1564
+ }
1565
+ }
1566
+
1567
+ static void setup_fields(JNIEnv* jenv, st_table** tbl, jobjectArray flds)
1568
+ {
1569
+ int i;
1570
+ jint modifier;
1571
+ jsize fcount = (*jenv)->GetArrayLength(jenv, flds);
1572
+ *tbl = st_init_numtable_with_size(fcount);
1573
+ for (i = 0; i < fcount; i++)
1574
+ {
1575
+ jobject f = (*jenv)->GetObjectArrayElement(jenv, flds, i);
1576
+ rjb_check_exception(jenv, 0);
1577
+ modifier = (*jenv)->CallIntMethod(jenv, f, field_getModifiers);
1578
+ create_fieldinfo(jenv, *tbl, f, modifier & ACC_FINAL, modifier & ACC_STATIC);
1579
+ (*jenv)->DeleteLocalRef(jenv, f);
1580
+ }
1581
+ }
1582
+
1583
+ static void load_constants(JNIEnv* jenv, jclass klass, VALUE self, jobjectArray flds)
1584
+ {
1585
+ int i;
1586
+ jint modifier;
1587
+ jsize fcount = (*jenv)->GetArrayLength(jenv, flds);
1588
+ for (i = 0; i < fcount; i++)
1589
+ {
1590
+ jobject f = (*jenv)->GetObjectArrayElement(jenv, flds, i);
1591
+ rjb_check_exception(jenv, 0);
1592
+ modifier = (*jenv)->CallIntMethod(jenv, f, field_getModifiers);
1593
+ rjb_check_exception(jenv, 0);
1594
+ if ((modifier & (ACC_PUBLIC | ACC_STATIC | ACC_FINAL)) == (ACC_PUBLIC | ACC_STATIC | ACC_FINAL))
1595
+ {
1596
+ jstring nm;
1597
+ const char* cname;
1598
+ jobject cls;
1599
+ char sig;
1600
+ char depth;
1601
+ off_t iv;
1602
+ J2R j2r;
1603
+ jvalue jv;
1604
+ jfieldID jfid;
1605
+ char sigs[256];
1606
+ char* pname;
1607
+
1608
+ /* constants make define directly in the ruby object */
1609
+ cls = (*jenv)->CallObjectMethod(jenv, f, field_getType);
1610
+ rjb_check_exception(jenv, 0);
1611
+ iv = 0;
1612
+ sig = depth = 0;
1613
+ j2r = get_j2r(jenv, cls, &sig, &depth, sigs, &iv, 1);
1614
+ if (!j2r) j2r = jv2rv;
1615
+ (*jenv)->DeleteLocalRef(jenv, cls);
1616
+ nm = (*jenv)->CallObjectMethod(jenv, f, field_getName);
1617
+ rjb_check_exception(jenv, 0);
1618
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1619
+ rjb_check_exception(jenv, 0);
1620
+ jfid = (*jenv)->GetStaticFieldID(jenv, klass, cname, sigs);
1621
+ rjb_check_exception(jenv, 0);
1622
+ switch (sig)
1623
+ {
1624
+ case 'D':
1625
+ jv.d = (*jenv)->GetStaticDoubleField(jenv, klass, jfid);
1626
+ break;
1627
+ case 'Z':
1628
+ jv.z = (*jenv)->GetStaticBooleanField(jenv, klass, jfid);
1629
+ break;
1630
+ case 'B':
1631
+ jv.b = (*jenv)->GetStaticByteField(jenv, klass, jfid);
1632
+ break;
1633
+ case 'F':
1634
+ jv.f = (*jenv)->GetStaticFloatField(jenv, klass, jfid);
1635
+ break;
1636
+ case 'C':
1637
+ jv.c = (*jenv)->GetStaticCharField(jenv, klass, jfid);
1638
+ break;
1639
+ case 'S':
1640
+ jv.s = (*jenv)->GetStaticShortField(jenv, klass, jfid);
1641
+ break;
1642
+ case 'J':
1643
+ jv.j = (*jenv)->GetStaticLongField(jenv, klass, jfid);
1644
+ break;
1645
+ case 'I':
1646
+ jv.i = (*jenv)->GetStaticIntField(jenv, klass, jfid);
1647
+ break;
1648
+ default:
1649
+ jv.l = (*jenv)->GetStaticObjectField(jenv, klass, jfid);
1650
+ break;
1651
+ }
1652
+ pname = (char*)cname;
1653
+ if (!isupper(*cname))
1654
+ {
1655
+ pname = ALLOCA_N(char, strlen(cname) + 1);
1656
+ strcpy(pname, cname);
1657
+ *pname = toupper(*pname);
1658
+ if (!isupper(*pname)
1659
+ || rb_const_defined(rb_obj_class(self), rb_intern(pname)))
1660
+ {
1661
+ pname = NULL;
1662
+ }
1663
+ }
1664
+ if (pname)
1665
+ {
1666
+ rb_define_const(rb_obj_class(self), pname, j2r(jenv, jv));
1667
+ }
1668
+ rjb_release_string(jenv, nm, cname);
1669
+ }
1670
+ (*jenv)->DeleteLocalRef(jenv, f);
1671
+ }
1672
+ }
1673
+
1674
+ static void setup_metadata(JNIEnv* jenv, VALUE self, struct jv_data* ptr, VALUE classname)
1675
+ {
1676
+ jmethodID mid;
1677
+ jobjectArray methods;
1678
+ jobjectArray flds;
1679
+
1680
+ jclass klass = (*jenv)->GetObjectClass(jenv, ptr->idata.obj);
1681
+ ptr->idata.klass = (*jenv)->NewGlobalRef(jenv, klass);
1682
+ rjb_check_exception(jenv, 0);
1683
+ mid = (*jenv)->GetMethodID(jenv, klass, "getMethods", "()[Ljava/lang/reflect/Method;");
1684
+ rjb_check_exception(jenv, 0);
1685
+ methods = (*jenv)->CallNonvirtualObjectMethod(jenv, ptr->idata.obj, klass, mid);
1686
+ rjb_check_exception(jenv, 0);
1687
+ setup_methods(jenv, &ptr->idata.methods, &ptr->static_methods, methods);
1688
+ mid = (*jenv)->GetMethodID(jenv, klass, "getConstructors", "()[Ljava/lang/reflect/Constructor;");
1689
+ rjb_check_exception(jenv, 0);
1690
+ methods = (*jenv)->CallNonvirtualObjectMethod(jenv, ptr->idata.obj, klass, mid);
1691
+ rjb_check_exception(jenv, 0);
1692
+ setup_constructors(jenv, &ptr->constructors, methods);
1693
+ mid = (*jenv)->GetMethodID(jenv, klass, "getFields", "()[Ljava/lang/reflect/Field;");
1694
+ rjb_check_exception(jenv, 0);
1695
+ flds = (*jenv)->CallNonvirtualObjectMethod(jenv, ptr->idata.obj, klass, mid);
1696
+ rjb_check_exception(jenv, 0);
1697
+ setup_fields(jenv, &ptr->idata.fields, flds);
1698
+
1699
+ register_class(self, classname);
1700
+ load_constants(jenv, ptr->idata.obj, self, flds);
1701
+ }
1702
+
1703
+ /*
1704
+ * load Java Virtual Machine
1705
+ * def load(class_path = '', vmargs = [])
1706
+ * class_path: passes for the class dir and jar name
1707
+ * vmargs: strng array of vmarg (such as -Xrs)
1708
+ *
1709
+ * change in rjb 0.1.7, omit first argument for JNI version.
1710
+ * because I misunderstood the number means (JVM but JNI).
1711
+ */
1712
+ static VALUE rjb_s_load(int argc, VALUE* argv, VALUE self)
1713
+ {
1714
+ JNIEnv* jenv;
1715
+ JavaVMInitArgs vm_args;
1716
+ jint res;
1717
+ VALUE classpath;
1718
+ VALUE user_path;
1719
+ VALUE vm_argv;
1720
+ char* userpath;
1721
+ ID stradd = rb_intern("<<");
1722
+ ID pathsep = rb_intern("PATH_SEPARATOR");
1723
+ int i;
1724
+ jclass jmethod;
1725
+ jclass jfield;
1726
+ jclass jconstructor;
1727
+
1728
+ if (rjb_jvm)
1729
+ {
1730
+ return Qnil;
1731
+ }
1732
+
1733
+ memset(&vm_args, 0, sizeof(vm_args));
1734
+ vm_args.version = JNI_VERSION_1_4;
1735
+ rb_scan_args(argc, argv, "02", &user_path, &vm_argv);
1736
+ if (!NIL_P(user_path))
1737
+ {
1738
+ Check_Type(user_path, T_STRING);
1739
+ }
1740
+ else
1741
+ {
1742
+ user_path = rb_str_new2(".");
1743
+ }
1744
+ classpath = rb_cvar_get(rjb, cvar_classpath);
1745
+ for (i = 0; i < RARRAY_LEN(classpath); i++)
1746
+ {
1747
+ rb_funcall(user_path, stradd, 1, rb_const_get(rb_cFile, pathsep));
1748
+ rb_funcall(user_path, stradd, 1, rb_ary_entry(classpath, 0));
1749
+ }
1750
+ userpath = StringValueCStr(user_path);
1751
+
1752
+ if (!NIL_P(vm_argv))
1753
+ {
1754
+ Check_Type(vm_argv, T_ARRAY);
1755
+ }
1756
+ jenv = NULL;
1757
+ res = rjb_create_jvm(&jenv, &vm_args, userpath, vm_argv);
1758
+ if (res < 0)
1759
+ {
1760
+ rjb_jvm = NULL;
1761
+ rb_raise(rb_eRuntimeError, "can't create Java VM");
1762
+ } else {
1763
+ main_jenv = jenv;
1764
+ }
1765
+
1766
+ RJB_FIND_CLASS(jconstructor, "java/lang/reflect/Constructor");
1767
+ RJB_LOAD_METHOD(ctrGetParameterTypes, jconstructor, "getParameterTypes", "()[Ljava/lang/Class;");
1768
+ RJB_FIND_CLASS(jmethod, "java/lang/reflect/Method");
1769
+ RJB_LOAD_METHOD(method_getModifiers, jmethod, "getModifiers", "()I");
1770
+ RJB_LOAD_METHOD(method_getName, jmethod, "getName", "()Ljava/lang/String;");
1771
+ RJB_LOAD_METHOD(getParameterTypes, jmethod, "getParameterTypes", "()[Ljava/lang/Class;");
1772
+ RJB_LOAD_METHOD(getReturnType, jmethod, "getReturnType", "()Ljava/lang/Class;");
1773
+ rjb_check_exception(jenv, 1);
1774
+
1775
+ RJB_FIND_CLASS(jfield, "java/lang/reflect/Field");
1776
+ RJB_LOAD_METHOD(field_getModifiers, jfield, "getModifiers", "()I");
1777
+ RJB_LOAD_METHOD(field_getName, jfield, "getName", "()Ljava/lang/String;");
1778
+ RJB_LOAD_METHOD(field_getType, jfield, "getType", "()Ljava/lang/Class;");
1779
+ rjb_check_exception(jenv, 1);
1780
+
1781
+ RJB_HOLD_CLASS(j_class, "java/lang/Class");
1782
+ RJB_LOAD_METHOD(rjb_class_getName, j_class, "getName", "()Ljava/lang/String;");
1783
+ rjb_check_exception(jenv, 1);
1784
+
1785
+ RJB_HOLD_CLASS(rjb_j_throwable, "java/lang/Throwable");
1786
+ RJB_LOAD_METHOD(rjb_throwable_getMessage, rjb_j_throwable, "getMessage", "()Ljava/lang/String;");
1787
+ rjb_check_exception(jenv, 1);
1788
+
1789
+ RJB_HOLD_CLASS(j_string, "java/lang/String");
1790
+ RJB_LOAD_METHOD(str_tostring, j_string, "toString", "()Ljava/lang/String;");
1791
+ rjb_check_exception(jenv, 1);
1792
+
1793
+ RJB_HOLD_CLASS(j_object, "java/lang/Object");
1794
+ rjb_check_exception(jenv, 1);
1795
+
1796
+ RJB_HOLD_CLASS(j_url, "java/net/URL");
1797
+ RJB_LOAD_METHOD(url_new, j_url, "<init>", "(Ljava/lang/String;)V");
1798
+ rjb_check_exception(jenv, 1);
1799
+
1800
+ for (i = PRM_INT; i < PRM_LAST; i++)
1801
+ {
1802
+ jclass klass;
1803
+ RJB_FIND_CLASS(klass, jpcvt[i].classname);
1804
+ if (i == PRM_BOOLEAN)
1805
+ {
1806
+ RJB_LOAD_STATIC_METHOD(jpcvt[i].ctr_id, klass, "valueOf", jpcvt[i].ctrsig);
1807
+ }
1808
+ else if (jpcvt[i].ctrsig)
1809
+ {
1810
+ RJB_LOAD_METHOD(jpcvt[i].ctr_id, klass, "<init>", jpcvt[i].ctrsig);
1811
+ }
1812
+ RJB_LOAD_METHOD(jpcvt[i].to_prim_id, klass,
1813
+ jpcvt[i].to_prim_method, jpcvt[i].prmsig);
1814
+
1815
+ jpcvt[i].klass = (*jenv)->NewGlobalRef(jenv, klass);
1816
+ }
1817
+
1818
+ jklass = import_class(jenv, j_class, rb_str_new2("java.lang.Class"));
1819
+ rb_define_method(rb_singleton_class(jklass), "forName", rjb_class_forname, -1);
1820
+ rb_define_alias(rb_singleton_class(jklass), "for_name", "forName");
1821
+ rb_gc_register_address(&jklass);
1822
+
1823
+ return Qnil;
1824
+ }
1825
+
1826
+ /*
1827
+ * load Java Virtual Machine with default arguments.
1828
+ */
1829
+ VALUE rjb_load_vm_default()
1830
+ {
1831
+ if (rjb_jvm) return Qfalse;
1832
+
1833
+ rb_warning("Rjb::implicit jvm loading");
1834
+ return rjb_s_load(0, NULL, 0);
1835
+ }
1836
+
1837
+ /*
1838
+ * common prelude
1839
+ */
1840
+ JNIEnv* rjb_prelude()
1841
+ {
1842
+ JNIEnv* jenv = NULL;
1843
+ rjb_load_vm_default();
1844
+ jenv = rjb_attach_current_thread();
1845
+ (*jenv)->ExceptionClear(jenv);
1846
+ return jenv;
1847
+ }
1848
+
1849
+ jobject get_systemloader(JNIEnv* jenv)
1850
+ {
1851
+ if (!j_classloader)
1852
+ {
1853
+ RJB_HOLD_CLASS(j_classloader, "java/lang/ClassLoader");
1854
+ RJB_LOAD_STATIC_METHOD(get_system_classloader, j_classloader,
1855
+ "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
1856
+ rjb_check_exception(jenv, 1);
1857
+ }
1858
+ return (*jenv)->CallStaticObjectMethod(jenv, j_classloader, get_system_classloader);
1859
+ }
1860
+
1861
+ static jobject get_class_loader(JNIEnv* jenv)
1862
+ {
1863
+ return (url_loader) ? url_loader : get_systemloader(jenv);
1864
+ }
1865
+
1866
+ /*
1867
+ * unload Java Virtual Machine
1868
+ *
1869
+ * def unload()
1870
+ * classes.clear
1871
+ * unload(jvm)
1872
+ * end
1873
+ */
1874
+ static int clear_classes(VALUE key, VALUE val, VALUE dummy)
1875
+ {
1876
+ return ST_DELETE;
1877
+ }
1878
+ static VALUE rjb_s_unload(int argc, VALUE* argv, VALUE self)
1879
+ {
1880
+ int result = 0;
1881
+ #if defined(HAVE_RB_HASH_FOREACH) || defined(RUBINIUS)
1882
+ rb_hash_foreach(rjb_loaded_classes, clear_classes, 0);
1883
+ #else
1884
+ #if defined(RHASH_TBL)
1885
+ st_foreach(RHASH_TBL(rjb_loaded_classes), clear_classes, 0);
1886
+ #else
1887
+ st_foreach(RHASH(rjb_loaded_classes)->tbl, clear_classes, 0);
1888
+ #endif
1889
+ #endif
1890
+
1891
+ if (rjb_jvm)
1892
+ {
1893
+ JNIEnv* jenv = rjb_attach_current_thread();
1894
+ (*jenv)->ExceptionClear(jenv);
1895
+ result = (*rjb_jvm)->DestroyJavaVM(rjb_jvm);
1896
+ rjb_jvm = NULL;
1897
+ rjb_unload_vm();
1898
+ }
1899
+ return INT2NUM(result);
1900
+ }
1901
+
1902
+ static VALUE rjb_s_loaded(VALUE self)
1903
+ {
1904
+ return (rjb_jvm) ? Qtrue : Qfalse;
1905
+ }
1906
+
1907
+ /*
1908
+ * return all classes that were already loaded.
1909
+ * this method simply returns the global hash,
1910
+ * but it's safe because the hash was frozen.
1911
+ */
1912
+ static VALUE rjb_s_classes(VALUE self)
1913
+ {
1914
+ return rjb_loaded_classes;
1915
+ }
1916
+
1917
+ /**
1918
+ * For JRuby conpatible option
1919
+ */
1920
+ static VALUE rjb_s_set_pconversion(VALUE self, VALUE val)
1921
+ {
1922
+ primitive_conversion = (RTEST(val)) ? Qtrue : Qfalse;
1923
+ return val;
1924
+ }
1925
+
1926
+ /**
1927
+ * For JRuby conpatible option
1928
+ */
1929
+ static VALUE rjb_s_get_pconversion(VALUE self)
1930
+ {
1931
+ return primitive_conversion;
1932
+ }
1933
+
1934
+
1935
+ /*
1936
+ * free java class
1937
+ */
1938
+ #if 0
1939
+ static void free_constructor(struct cls_constructor* p)
1940
+ {
1941
+ free(p->arg_convert);
1942
+ free(p->method_signature);
1943
+ }
1944
+ static int free_method_item(ID key, struct cls_method* pm, int dummy)
1945
+ {
1946
+ for (; pm; pm = pm->next)
1947
+ {
1948
+ free_constructor(&pm->basic);
1949
+ }
1950
+ return ST_CONTINUE;
1951
+ }
1952
+ #endif
1953
+
1954
+ /*
1955
+ * finalize Object instance
1956
+ */
1957
+ static VALUE rjb_delete_ref(struct jvi_data* ptr)
1958
+ {
1959
+ JNIEnv* jenv = rjb_attach_current_thread();
1960
+ if (jenv)
1961
+ {
1962
+ (*jenv)->DeleteGlobalRef(jenv, ptr->obj);
1963
+ }
1964
+ return Qnil;
1965
+ }
1966
+
1967
+ /*
1968
+ * finalize Bridge instance
1969
+ */
1970
+ static VALUE rj_bridge_free(struct rj_bridge* ptr)
1971
+ {
1972
+ JNIEnv* jenv = rjb_attach_current_thread();
1973
+ if (jenv)
1974
+ {
1975
+ (*jenv)->DeleteLocalRef(jenv, ptr->proxy);
1976
+ (*jenv)->DeleteLocalRef(jenv, ptr->bridge);
1977
+ }
1978
+ return Qnil;
1979
+ }
1980
+
1981
+ /*
1982
+ * mark wrapped object in the Bridge
1983
+ */
1984
+ static void rj_bridge_mark(struct rj_bridge* ptr)
1985
+ {
1986
+ rb_gc_mark(ptr->wrapped);
1987
+ }
1988
+
1989
+ /*
1990
+ * finalize Class instance
1991
+ */
1992
+ static VALUE rjb_s_free(struct jv_data* ptr)
1993
+ {
1994
+ /* class never delete
1995
+ JNIEnv* jenv = rjb_attach_current_thread();
1996
+ struct cls_constructor** c;
1997
+
1998
+ rjb_delete_ref(&ptr->idata);
1999
+ if (ptr->constructors)
2000
+ {
2001
+ for (c = ptr->constructors; *c; c++)
2002
+ {
2003
+ free_constructor(*c);
2004
+ }
2005
+ }
2006
+ free(ptr->constructors);
2007
+ if (ptr->idata.methods)
2008
+ {
2009
+ st_foreach(ptr->idata.methods, (int(*)())free_method_item, 0);
2010
+ st_free_table(ptr->idata.methods);
2011
+ }
2012
+ (*jenv)->DeleteGlobalRef(jenv, ptr->idata.klass);
2013
+ st_delete(RHASH(rjb_loaded_classes)->tbl, clsname, NULL);
2014
+ */
2015
+ return Qnil;
2016
+ }
2017
+
2018
+ /*
2019
+ * create new instance of this class
2020
+ */
2021
+ static VALUE createinstance(JNIEnv* jenv, int argc, VALUE* argv,
2022
+ VALUE self, struct cls_constructor* pc)
2023
+ {
2024
+ int i;
2025
+ char* psig = pc->method_signature;
2026
+ jobject obj = NULL;
2027
+ VALUE result;
2028
+ struct jv_data* jklass;
2029
+ struct jvi_data* org;
2030
+ jvalue* args = (argc) ? ALLOCA_N(jvalue, argc) : NULL;
2031
+
2032
+ Data_Get_Struct(self, struct jv_data, jklass);
2033
+ org = &jklass->idata;
2034
+
2035
+ for (i = 0; i < argc; i++)
2036
+ {
2037
+ R2J pr2j = *(pc->arg_convert + i);
2038
+ pr2j(jenv, argv[i], args + i, psig, 0);
2039
+ psig = next_sig(psig);
2040
+ rjb_check_exception(jenv, 1);
2041
+ }
2042
+ obj = (*jenv)->NewObjectA(jenv, org->obj, pc->id, args);
2043
+ if (!obj)
2044
+ {
2045
+ rjb_check_exception(jenv, 1);
2046
+ }
2047
+ psig = pc->method_signature;
2048
+ for (i = 0; i < argc; i++)
2049
+ {
2050
+ R2J pr2j = *(pc->arg_convert + i);
2051
+ pr2j(jenv, argv[i], args + i, psig, 1);
2052
+ psig = next_sig(psig);
2053
+ }
2054
+
2055
+ result = register_instance(jenv, self, jklass, obj);
2056
+ (*jenv)->DeleteLocalRef(jenv, obj);
2057
+ return result;
2058
+ }
2059
+
2060
+ static VALUE import_class(JNIEnv* jenv, jclass jcls, VALUE clsname)
2061
+ {
2062
+ VALUE v;
2063
+ VALUE rexp;
2064
+ struct jv_data* ptr;
2065
+ char* pclsname = StringValueCStr(clsname);
2066
+ char* nm = ALLOCA_N(char, strlen(pclsname) + 1);
2067
+ strcpy(nm, pclsname);
2068
+ *nm = toupper(*nm);
2069
+ for (pclsname = nm; *pclsname; pclsname++)
2070
+ {
2071
+ if (*pclsname == '.')
2072
+ {
2073
+ *pclsname = '_';
2074
+ }
2075
+ }
2076
+ rexp = rb_define_class_under(rjb, nm, rjbc);
2077
+ ptr = ALLOC(struct jv_data);
2078
+ memset(ptr, 0, sizeof(struct jv_data));
2079
+ v = Data_Wrap_Struct(rexp, NULL, rjb_s_free, ptr);
2080
+ ptr->idata.obj = (*jenv)->NewGlobalRef(jenv, jcls);
2081
+ setup_metadata(jenv, v, ptr, clsname);
2082
+ return v;
2083
+ }
2084
+
2085
+ static VALUE rjb_a_initialize(VALUE self, VALUE proc)
2086
+ {
2087
+ return rb_ivar_set(self, anonymousblock, proc);
2088
+ }
2089
+
2090
+ static VALUE rjb_a_missing(int argc, VALUE* argv, VALUE self)
2091
+ {
2092
+ VALUE proc = rb_ivar_get(self, anonymousblock);
2093
+ return rb_funcall2(proc, id_call, argc, argv);
2094
+ }
2095
+
2096
+ static VALUE rjb_i_prepare_proxy(VALUE self)
2097
+ {
2098
+ return rb_funcall(self, rb_intern("instance_eval"), 1,
2099
+ rb_str_new2("instance_eval(&" USER_INITIALIZE ")"));
2100
+ }
2101
+
2102
+ static VALUE register_instance(JNIEnv* jenv, VALUE klass, struct jv_data* org, jobject obj)
2103
+ {
2104
+ volatile VALUE v;
2105
+ VALUE iproc;
2106
+ struct jvi_data* ptr = ALLOC(struct jvi_data);
2107
+ memset(ptr, 0, sizeof(struct jvi_data));
2108
+ v = Data_Wrap_Struct(rjbi, NULL, rjb_delete_ref, ptr);
2109
+ ptr->klass = org->idata.obj;
2110
+ ptr->obj = (*jenv)->NewGlobalRef(jenv, obj);
2111
+ ptr->methods = org->idata.methods;
2112
+ ptr->fields = org->idata.fields;
2113
+ iproc = rb_ivar_get(klass, user_initialize);
2114
+ if (iproc != Qnil)
2115
+ {
2116
+ rb_ivar_set(v, user_initialize, iproc);
2117
+ rb_funcall(v, rb_intern("_prepare_proxy"), 0, 0);
2118
+ }
2119
+ rb_funcall(v, initialize_proxy, 0, 0);
2120
+ return v;
2121
+ }
2122
+
2123
+ /*
2124
+ * temporary signature check
2125
+ * return !0 if found
2126
+ */
2127
+ static int check_rtype(JNIEnv* jenv, VALUE* pv, char* p)
2128
+ {
2129
+ char* pcls = NULL;
2130
+ if (*p == 'L')
2131
+ {
2132
+ char* pt = strchr(p, ';');
2133
+ if (pt) {
2134
+ size_t len = pt - p - 1;
2135
+ pcls = ALLOCA_N(char, len + 1);
2136
+ strncpy(pcls, p + 1, len);
2137
+ *(pcls + len) = '\0';
2138
+ }
2139
+ }
2140
+ if (pcls && !strcmp("java.lang.Object", pcls))
2141
+ {
2142
+ return 1;
2143
+ }
2144
+ switch (TYPE(*pv))
2145
+ {
2146
+ case T_FIXNUM:
2147
+ return strchr("BCDFIJS", *p) != NULL;
2148
+ case T_BIGNUM:
2149
+ return strchr("BCDFIJS", *p) != NULL;
2150
+ case T_FLOAT:
2151
+ return strchr("DF", *p) != NULL;
2152
+ case T_STRING:
2153
+ return pcls && !strcmp("java.lang.String", pcls) || *p == '[' && *(p + 1) == 'B';
2154
+ case T_TRUE:
2155
+ case T_FALSE:
2156
+ return *p == 'Z';
2157
+ case T_ARRAY:
2158
+ return *p == '[';
2159
+ case T_DATA:
2160
+ if (IS_RJB_OBJECT(*pv) && pcls)
2161
+ {
2162
+ /* imported object */
2163
+ jclass cls;
2164
+ struct jvi_data* ptr;
2165
+ int result = 0;
2166
+ if (!strcmp("java.lang.String", pcls)) return 1;
2167
+ Data_Get_Struct(*pv, struct jvi_data, ptr);
2168
+ RJB_FIND_CLASS(cls, java2jniname(pcls));
2169
+ if (cls)
2170
+ {
2171
+ result = (cls && (*jenv)->IsInstanceOf(jenv, ptr->obj, cls));
2172
+ (*jenv)->DeleteLocalRef(jenv, cls);
2173
+ }
2174
+ return result;
2175
+ } else if (pcls) {
2176
+ VALUE blockobj = rb_class_new_instance(1, pv, rjba);
2177
+ *pv = rjb_s_bind(rjbb, blockobj, rb_str_new2(pcls));
2178
+ }
2179
+ /* fall down to the next case */
2180
+ case T_OBJECT:
2181
+ /* fall down to the next case */
2182
+ default:
2183
+ if (pcls || *p == '[')
2184
+ {
2185
+ return 1;
2186
+ }
2187
+ return 0;
2188
+ }
2189
+ }
2190
+
2191
+ /*
2192
+ * new instance with signature
2193
+ */
2194
+ static VALUE rjb_newinstance_s(int argc, VALUE* argv, VALUE self)
2195
+ {
2196
+ VALUE vsig, rest;
2197
+ char* sig;
2198
+ VALUE ret = Qnil;
2199
+ struct jv_data* ptr;
2200
+ int found = 0;
2201
+ JNIEnv* jenv = rjb_prelude();
2202
+
2203
+ rb_scan_args(argc, argv, "1*", &vsig, &rest);
2204
+ sig = StringValueCStr(vsig);
2205
+ Data_Get_Struct(self, struct jv_data, ptr);
2206
+ if (ptr->constructors)
2207
+ {
2208
+ struct cls_constructor** pc = ptr->constructors;
2209
+ for (pc = ptr->constructors; *pc; pc++)
2210
+ {
2211
+ if ((*pc)->arg_count == argc - 1
2212
+ && !strcmp(sig, (*pc)->method_signature))
2213
+ {
2214
+ found = 1;
2215
+ ret = createinstance(jenv, argc - 1, argv + 1, self, *pc);
2216
+ break;
2217
+ }
2218
+ }
2219
+ }
2220
+ if (!found) {
2221
+ rb_raise(rb_eRuntimeError, "Constructor not found");
2222
+ }
2223
+ return ret;
2224
+ }
2225
+
2226
+ static VALUE rjb_newinstance(int argc, VALUE* argv, VALUE self)
2227
+ {
2228
+ VALUE ret = Qnil;
2229
+ struct jv_data* ptr;
2230
+ struct cls_constructor** pc;
2231
+ int found = 0;
2232
+ JNIEnv* jenv = rjb_prelude();
2233
+
2234
+ Data_Get_Struct(self, struct jv_data, ptr);
2235
+
2236
+ if (ptr->constructors)
2237
+ {
2238
+ int i;
2239
+ char* psig;
2240
+ for (pc = ptr->constructors; *pc; pc++)
2241
+ {
2242
+ if ((*pc)->arg_count == argc)
2243
+ {
2244
+ found = 1;
2245
+ psig = (*pc)->method_signature;
2246
+ for (i = 0; i < argc; i++)
2247
+ {
2248
+ if (!check_rtype(jenv, argv + i, psig))
2249
+ {
2250
+ found = 0;
2251
+ break;
2252
+ }
2253
+ psig = next_sig(psig);
2254
+ }
2255
+ if (found)
2256
+ {
2257
+ ret = createinstance(jenv, argc, argv, self, *pc);
2258
+ break;
2259
+ }
2260
+ }
2261
+ }
2262
+ }
2263
+ if (!found) {
2264
+ rb_raise(rb_eRuntimeError, "Constructor not found");
2265
+ }
2266
+ return ret;
2267
+ }
2268
+
2269
+ /*
2270
+ * find java class using added classloader
2271
+ */
2272
+ jclass rjb_find_class_by_name(JNIEnv* jenv, const char* name)
2273
+ {
2274
+ jclass cls;
2275
+ if (url_loader)
2276
+ {
2277
+ jvalue v;
2278
+ char* binname = ALLOCA_N(char, strlen(name) + 32);
2279
+ strcpy(binname, name);
2280
+ v.l = (*jenv)->NewStringUTF(jenv, jniname2java(binname));
2281
+ cls = (*jenv)->CallObjectMethod(jenv, url_loader, rjb_load_class, v);
2282
+ (*jenv)->DeleteLocalRef(jenv, v.l);
2283
+ }
2284
+ else
2285
+ {
2286
+ cls = (*jenv)->FindClass(jenv, name);
2287
+ }
2288
+ return cls;
2289
+ }
2290
+
2291
+ /*
2292
+ * find java class from classname
2293
+ */
2294
+ jclass rjb_find_class(JNIEnv* jenv, VALUE name)
2295
+ {
2296
+ char* cname;
2297
+ char* jnicls;
2298
+
2299
+ Check_Type(name, T_STRING);
2300
+ cname = StringValueCStr(name);
2301
+ jnicls = ALLOCA_N(char, strlen(cname) + 1);
2302
+ strcpy(jnicls, cname);
2303
+ return rjb_find_class_by_name(jenv, java2jniname(jnicls));
2304
+ }
2305
+
2306
+ /*
2307
+ * get specified method signature
2308
+ */
2309
+ static VALUE get_signatures(VALUE mname, st_table* st)
2310
+ {
2311
+ VALUE ret;
2312
+ struct cls_method* pm;
2313
+ ID rmid = rb_to_id(mname);
2314
+
2315
+ if (!st_lookup(st, rmid, (st_data_t*)&pm))
2316
+ {
2317
+ const char* tname = rb_id2name(rmid);
2318
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s'", tname);
2319
+ }
2320
+ ret = rb_ary_new();
2321
+ for (; pm; pm = pm->next)
2322
+ {
2323
+ if (pm->basic.method_signature) {
2324
+ rb_ary_push(ret, rb_str_new2(pm->basic.method_signature));
2325
+ } else {
2326
+ rb_ary_push(ret, Qnil);
2327
+ }
2328
+ }
2329
+ return ret;
2330
+ }
2331
+
2332
+ static VALUE rjb_get_signatures(VALUE self, VALUE mname)
2333
+ {
2334
+ struct jv_data* ptr;
2335
+
2336
+ Data_Get_Struct(self, struct jv_data, ptr);
2337
+ return get_signatures(mname, ptr->idata.methods);
2338
+ }
2339
+
2340
+ static VALUE rjb_get_static_signatures(VALUE self, VALUE mname)
2341
+ {
2342
+ struct jv_data* ptr;
2343
+
2344
+ Data_Get_Struct(self, struct jv_data, ptr);
2345
+ return get_signatures(mname, ptr->static_methods);
2346
+ }
2347
+
2348
+ static VALUE rjb_get_ctor_signatures(VALUE self)
2349
+ {
2350
+ VALUE ret;
2351
+ struct jv_data* ptr;
2352
+ struct cls_constructor** pc;
2353
+
2354
+ Data_Get_Struct(self, struct jv_data, ptr);
2355
+ ret = rb_ary_new();
2356
+ if (ptr->constructors)
2357
+ {
2358
+ for (pc = ptr->constructors; *pc; pc++)
2359
+ {
2360
+ rb_ary_push(ret, rb_str_new2((*pc)->method_signature));
2361
+ }
2362
+ }
2363
+ return ret;
2364
+ }
2365
+
2366
+ /*
2367
+ * jclass Rjb::bind(rbobj, interface_name)
2368
+ */
2369
+ static VALUE rjb_s_bind(VALUE self, VALUE rbobj, VALUE itfname)
2370
+ {
2371
+ VALUE result = Qnil;
2372
+ jclass itf;
2373
+ JNIEnv* jenv = rjb_prelude();
2374
+
2375
+ itf = rjb_find_class(jenv, itfname);
2376
+ rjb_check_exception(jenv, 1);
2377
+ if (itf)
2378
+ {
2379
+ struct rj_bridge* ptr = ALLOC(struct rj_bridge);
2380
+ memset(ptr, 0, sizeof(struct rj_bridge));
2381
+ ptr->bridge = (*jenv)->NewGlobalRef(jenv,
2382
+ (*jenv)->AllocObject(jenv, rjb_rbridge));
2383
+ if (!ptr->bridge)
2384
+ {
2385
+ free(ptr);
2386
+ rjb_check_exception(jenv, 1);
2387
+ return Qnil;
2388
+ }
2389
+ ptr->proxy = (*jenv)->CallObjectMethod(jenv, ptr->bridge,
2390
+ rjb_register_bridge, itf);
2391
+ ptr->proxy = (*jenv)->NewGlobalRef(jenv, ptr->proxy);
2392
+ ptr->wrapped = rbobj;
2393
+ result = Data_Wrap_Struct(rjbb, rj_bridge_mark, rj_bridge_free, ptr);
2394
+ rb_ary_push(proxies, result);
2395
+ rb_ivar_set(result, rb_intern("@wrapped"), rbobj);
2396
+ }
2397
+ return result;
2398
+ }
2399
+
2400
+ /*
2401
+ * Rjb's class is not Class but Object, so add class_eval for the Java class.
2402
+ */
2403
+ static VALUE rjb_class_eval(int argc, VALUE* argv, VALUE self)
2404
+ {
2405
+ if (rb_block_given_p())
2406
+ {
2407
+ rb_ivar_set(self, user_initialize, rb_block_proc());
2408
+ }
2409
+ return self;
2410
+ }
2411
+
2412
+ static VALUE rjb_s_impl(VALUE self)
2413
+ {
2414
+ VALUE obj;
2415
+ VALUE proc;
2416
+ rb_need_block();
2417
+ proc = rb_block_proc();
2418
+ obj = rb_class_new_instance(1, &proc, rjba);
2419
+ return rjb_s_bind(rjbb, obj, rb_funcall(self, rb_intern("name"), 0));
2420
+ }
2421
+
2422
+
2423
+ /*
2424
+ * jclass Rjb::bind(rbobj, interface_name)
2425
+ */
2426
+ static VALUE rjb_s_unbind(VALUE self, VALUE rbobj)
2427
+ {
2428
+ #if defined(RUBINIUS)
2429
+ return rb_funcall(proxies, rb_intern("delete"), 1, rbobj);
2430
+ #else
2431
+ return rb_ary_delete(proxies, rbobj);
2432
+ #endif
2433
+ }
2434
+
2435
+ /*
2436
+ * Jclass Rjb::import(classname)
2437
+ */
2438
+ static VALUE rjb_s_import(VALUE self, VALUE clsname)
2439
+ {
2440
+ JNIEnv* jenv;
2441
+ jclass jcls;
2442
+ VALUE v = rb_hash_aref(rjb_loaded_classes, clsname);
2443
+ if (v != Qnil)
2444
+ {
2445
+ return v;
2446
+ }
2447
+
2448
+ jenv = rjb_prelude();
2449
+ jcls = rjb_find_class(jenv, clsname);
2450
+ if (!jcls)
2451
+ {
2452
+ rjb_check_exception(jenv, 0);
2453
+ rb_raise(rb_eRuntimeError, "`%s' not found", StringValueCStr(clsname));
2454
+ }
2455
+ v = import_class(jenv, jcls, clsname);
2456
+ return v;
2457
+ }
2458
+
2459
+ static void register_class(VALUE self, VALUE clsname)
2460
+ {
2461
+ rb_define_singleton_method(self, "new", rjb_newinstance, -1);
2462
+ rb_define_singleton_method(self, "new_with_sig", rjb_newinstance_s, -1);
2463
+ rb_define_singleton_method(self, "class_eval", rjb_class_eval, -1);
2464
+ rb_define_singleton_method(self, "sigs", rjb_get_signatures, 1);
2465
+ rb_define_singleton_method(self, "static_sigs", rjb_get_static_signatures, 1);
2466
+ rb_define_singleton_method(self, "ctor_sigs", rjb_get_ctor_signatures, 0);
2467
+ rb_ivar_set(self, user_initialize, Qnil);
2468
+ /*
2469
+ * the hash was frozen, so it need to call st_ func directly.
2470
+ */
2471
+
2472
+ #if defined(HAVE_RB_HASH_ASET) || defined(RUBINIUS)
2473
+ rb_hash_aset(rjb_loaded_classes, clsname, self);
2474
+ #else
2475
+ #ifdef RHASH_TBL
2476
+ st_insert(RHASH_TBL(rjb_loaded_classes), clsname, self);
2477
+ #else
2478
+ st_insert(RHASH(rjb_loaded_classes)->tbl, clsname, self);
2479
+ #endif
2480
+ #endif
2481
+ }
2482
+
2483
+ static jobject conv_jarname_to_url(JNIEnv* jenv, VALUE jarname)
2484
+ {
2485
+ jvalue arg;
2486
+ jobject url;
2487
+ #if defined(DOSISH)
2488
+ size_t len;
2489
+ #endif
2490
+ char* jarp;
2491
+ char* urlp;
2492
+
2493
+ SafeStringValue(jarname);
2494
+ jarp = StringValueCStr(jarname);
2495
+ urlp = ALLOCA_N(char, strlen(jarp) + 32);
2496
+ if (strncmp(jarp, "http:", 5) && strncmp(jarp, "https:", 6))
2497
+ {
2498
+ #if defined(DOSISH)
2499
+ if (strlen(jarp) > 1 && jarp[1] == ':')
2500
+ {
2501
+ sprintf(urlp, "file:///%s", jarp);
2502
+ }
2503
+ else
2504
+ #endif
2505
+ {
2506
+ sprintf(urlp, "file://%s", jarp);
2507
+ }
2508
+ }
2509
+ else
2510
+ {
2511
+ strcpy(urlp, jarp);
2512
+ }
2513
+ #if defined(DOSISH)
2514
+ for (len = 0; len < strlen(urlp); len++)
2515
+ {
2516
+ if (urlp[len] == '\\')
2517
+ {
2518
+ urlp[len] = '/';
2519
+ }
2520
+ }
2521
+ #endif
2522
+ arg.l = (*jenv)->NewStringUTF(jenv, urlp);
2523
+ rjb_check_exception(jenv, 0);
2524
+ url = (*jenv)->NewObject(jenv, j_url, url_new, arg);
2525
+ rjb_check_exception(jenv, 0);
2526
+ return url;
2527
+ }
2528
+
2529
+ /*
2530
+ * Rjb::add_classpath(jarname)
2531
+ */
2532
+ static VALUE rjb_s_add_classpath(VALUE self, VALUE jarname)
2533
+ {
2534
+ VALUE cpath = rb_cvar_get(self, cvar_classpath);
2535
+ SafeStringValue(jarname);
2536
+ rb_ary_push(cpath, jarname);
2537
+ return cpath;
2538
+ }
2539
+
2540
+ /*
2541
+ * Rjb::add_jar(jarname)
2542
+ */
2543
+ static VALUE rjb_s_add_jar(VALUE self, VALUE jarname)
2544
+ {
2545
+ size_t i;
2546
+ JNIEnv* jenv;
2547
+ size_t count;
2548
+ jvalue args[2];
2549
+
2550
+ if (rb_type(jarname) != T_ARRAY)
2551
+ {
2552
+ SafeStringValue(jarname);
2553
+ count = 0;
2554
+ }
2555
+ else
2556
+ {
2557
+ count = RARRAY_LEN(jarname);
2558
+ }
2559
+ jenv = rjb_prelude();
2560
+ if (!j_url_loader)
2561
+ {
2562
+ j_url_loader = (*jenv)->NewGlobalRef(jenv,
2563
+ (*jenv)->FindClass(jenv, "java/net/URLClassLoader"));
2564
+ RJB_LOAD_METHOD(rjb_load_class, j_url_loader, "loadClass",
2565
+ "(Ljava/lang/String;)Ljava/lang/Class;");
2566
+ RJB_LOAD_METHOD(url_loader_new, j_url_loader, "<init>",
2567
+ "([Ljava/net/URL;Ljava/lang/ClassLoader;)V");
2568
+ RJB_LOAD_METHOD(url_geturls, j_url_loader, "getURLs",
2569
+ "()[Ljava/net/URL;");
2570
+ RJB_LOAD_METHOD(url_add_url, j_url_loader, "addURL",
2571
+ "(Ljava/net/URL;)V");
2572
+ }
2573
+ if (!url_loader)
2574
+ {
2575
+ args[0].l = (*jenv)->NewObjectArray(jenv, (jsize)((count == 0) ? 1 : count), j_url, NULL);
2576
+ rjb_check_exception(jenv, 0);
2577
+ if (!count)
2578
+ {
2579
+ (*jenv)->SetObjectArrayElement(jenv, args[0].l, 0,
2580
+ conv_jarname_to_url(jenv, jarname));
2581
+ }
2582
+ else
2583
+ {
2584
+ for (i = 0; i < count; i++) {
2585
+ (*jenv)->SetObjectArrayElement(jenv, args[0].l, (jint)i,
2586
+ conv_jarname_to_url(jenv, rb_ary_entry(jarname, i)));
2587
+ }
2588
+ }
2589
+ rjb_check_exception(jenv, 0);
2590
+ args[1].l = get_class_loader(jenv);
2591
+ url_loader = (*jenv)->NewObjectA(jenv, j_url_loader, url_loader_new, args);
2592
+ rjb_check_exception(jenv, 0);
2593
+ (*jenv)->NewGlobalRef(jenv, url_loader);
2594
+ (*jenv)->DeleteLocalRef(jenv, args[0].l);
2595
+ }
2596
+ else
2597
+ {
2598
+ jvalue v;
2599
+ if (count)
2600
+ {
2601
+ for (i = 0; i < count; i++)
2602
+ {
2603
+ v.l = conv_jarname_to_url(jenv, rb_ary_entry(jarname, i));
2604
+ (*jenv)->CallObjectMethod(jenv, url_loader, url_add_url, v);
2605
+ rjb_check_exception(jenv, 0);
2606
+ (*jenv)->DeleteLocalRef(jenv, v.l);
2607
+ }
2608
+ }
2609
+ else
2610
+ {
2611
+ v.l = conv_jarname_to_url(jenv, jarname);
2612
+ (*jenv)->CallObjectMethod(jenv, url_loader, url_add_url, v);
2613
+ rjb_check_exception(jenv, 0);
2614
+ (*jenv)->DeleteLocalRef(jenv, v.l);
2615
+ }
2616
+ }
2617
+ return Qtrue;
2618
+ }
2619
+
2620
+ static VALUE rjb_s_urls(VALUE self)
2621
+ {
2622
+ JNIEnv* jenv;
2623
+ jvalue ret;
2624
+ if (!url_loader) return Qnil;
2625
+ jenv = rjb_prelude();
2626
+ ret.l = (*jenv)->CallObjectMethod(jenv, url_loader, url_geturls);
2627
+ return jarray2rv(jenv, ret);
2628
+ }
2629
+
2630
+
2631
+ /*
2632
+ * return class name
2633
+ */
2634
+ static VALUE rjb_i_class(VALUE self)
2635
+ {
2636
+ JNIEnv* jenv = rjb_attach_current_thread();
2637
+ struct jvi_data* ptr;
2638
+ jstring nm;
2639
+ Data_Get_Struct(self, struct jvi_data, ptr);
2640
+ nm = (*jenv)->CallObjectMethod(jenv, ptr->klass, rjb_class_getName);
2641
+ rjb_check_exception(jenv, 0);
2642
+ return jstring2val(jenv, nm);
2643
+ }
2644
+
2645
+ /*
2646
+ * invoker
2647
+ */
2648
+ static VALUE getter(JNIEnv* jenv, struct cls_field* pf, struct jvi_data* ptr)
2649
+ {
2650
+ jvalue jv;
2651
+ switch (pf->result_signature)
2652
+ {
2653
+ case 'D':
2654
+ if (pf->static_field)
2655
+ {
2656
+ jv.d = (*jenv)->GetStaticDoubleField(jenv, ptr->klass, pf->id);
2657
+ }
2658
+ else
2659
+ {
2660
+ jv.d = (*jenv)->GetDoubleField(jenv, ptr->obj, pf->id);
2661
+ }
2662
+ break;
2663
+ case 'Z':
2664
+ if (pf->static_field)
2665
+ {
2666
+ jv.z = (*jenv)->GetStaticBooleanField(jenv, ptr->klass, pf->id);
2667
+ }
2668
+ else
2669
+ {
2670
+ jv.z = (*jenv)->GetBooleanField(jenv, ptr->obj, pf->id);
2671
+ }
2672
+ break;
2673
+ case 'B':
2674
+ if (pf->static_field)
2675
+ {
2676
+ jv.b = (*jenv)->GetStaticByteField(jenv, ptr->klass, pf->id);
2677
+ }
2678
+ else
2679
+ {
2680
+ jv.b = (*jenv)->GetByteField(jenv, ptr->obj, pf->id);
2681
+ }
2682
+ break;
2683
+ case 'F':
2684
+ if (pf->static_field)
2685
+ {
2686
+ jv.f = (*jenv)->GetStaticFloatField(jenv, ptr->klass, pf->id);
2687
+ }
2688
+ else
2689
+ {
2690
+ jv.f = (*jenv)->GetFloatField(jenv, ptr->obj, pf->id);
2691
+ }
2692
+ break;
2693
+ case 'C':
2694
+ if (pf->static_field)
2695
+ {
2696
+ jv.c = (*jenv)->GetStaticCharField(jenv, ptr->klass, pf->id);
2697
+ }
2698
+ else
2699
+ {
2700
+ jv.c = (*jenv)->GetCharField(jenv, ptr->obj, pf->id);
2701
+ }
2702
+ break;
2703
+ case 'S':
2704
+ if (pf->static_field)
2705
+ {
2706
+ jv.s = (*jenv)->GetStaticShortField(jenv, ptr->klass, pf->id);
2707
+ }
2708
+ else
2709
+ {
2710
+ jv.s = (*jenv)->GetShortField(jenv, ptr->obj, pf->id);
2711
+ }
2712
+ break;
2713
+ case 'J':
2714
+ if (pf->static_field)
2715
+ {
2716
+ jv.j = (*jenv)->GetStaticLongField(jenv, ptr->klass, pf->id);
2717
+ }
2718
+ else
2719
+ {
2720
+ jv.j = (*jenv)->GetLongField(jenv, ptr->obj, pf->id);
2721
+ }
2722
+ break;
2723
+ case 'I':
2724
+ if (pf->static_field)
2725
+ {
2726
+ jv.i = (*jenv)->GetStaticIntField(jenv, ptr->klass, pf->id);
2727
+ }
2728
+ else
2729
+ {
2730
+ jv.i = (*jenv)->GetIntField(jenv, ptr->obj, pf->id);
2731
+ }
2732
+ break;
2733
+ default:
2734
+ if (pf->static_field)
2735
+ {
2736
+ jv.l = (*jenv)->GetStaticObjectField(jenv, ptr->klass, pf->id);
2737
+ }
2738
+ else
2739
+ {
2740
+ jv.l = (*jenv)->GetObjectField(jenv, ptr->obj, pf->id);
2741
+ }
2742
+ break;
2743
+ }
2744
+ if (pf->result_arraydepth)
2745
+ {
2746
+ return ja2r(pf->value_convert, jenv, jv, pf->result_arraydepth);
2747
+ }
2748
+ else
2749
+ {
2750
+ return pf->value_convert(jenv, jv);
2751
+ }
2752
+ }
2753
+
2754
+ static void setter(JNIEnv* jenv, struct cls_field* pf, struct jvi_data* ptr, VALUE val)
2755
+ {
2756
+ jvalue jv;
2757
+ pf->arg_convert(jenv, val, &jv, pf->field_signature, 0);
2758
+ switch (*pf->field_signature)
2759
+ {
2760
+ case 'D':
2761
+ if (pf->static_field)
2762
+ {
2763
+ (*jenv)->SetStaticDoubleField(jenv, ptr->klass, pf->id, jv.d);
2764
+ }
2765
+ else
2766
+ {
2767
+ (*jenv)->SetDoubleField(jenv, ptr->obj, pf->id, jv.d);
2768
+ }
2769
+ break;
2770
+ case 'Z':
2771
+ if (pf->static_field)
2772
+ {
2773
+ (*jenv)->SetStaticBooleanField(jenv, ptr->klass, pf->id, jv.z);
2774
+ }
2775
+ else
2776
+ {
2777
+ (*jenv)->SetBooleanField(jenv, ptr->obj, pf->id, jv.z);
2778
+ }
2779
+ break;
2780
+ case 'B':
2781
+ if (pf->static_field)
2782
+ {
2783
+ (*jenv)->SetStaticByteField(jenv, ptr->klass, pf->id, jv.b);
2784
+ }
2785
+ else
2786
+ {
2787
+ (*jenv)->SetByteField(jenv, ptr->obj, pf->id, jv.b);
2788
+ }
2789
+ break;
2790
+ case 'F':
2791
+ if (pf->static_field)
2792
+ {
2793
+ (*jenv)->SetStaticFloatField(jenv, ptr->klass, pf->id, jv.f);
2794
+ }
2795
+ else
2796
+ {
2797
+ (*jenv)->SetFloatField(jenv, ptr->obj, pf->id, jv.f);
2798
+ }
2799
+ break;
2800
+ case 'C':
2801
+ if (pf->static_field)
2802
+ {
2803
+ (*jenv)->SetStaticCharField(jenv, ptr->klass, pf->id, jv.c);
2804
+ }
2805
+ else
2806
+ {
2807
+ (*jenv)->SetCharField(jenv, ptr->obj, pf->id, jv.c);
2808
+ }
2809
+ break;
2810
+ case 'S':
2811
+ if (pf->static_field)
2812
+ {
2813
+ (*jenv)->SetStaticShortField(jenv, ptr->klass, pf->id, jv.s);
2814
+ }
2815
+ else
2816
+ {
2817
+ (*jenv)->SetShortField(jenv, ptr->obj, pf->id, jv.s);
2818
+ }
2819
+ break;
2820
+ case 'J':
2821
+ if (pf->static_field)
2822
+ {
2823
+ (*jenv)->SetStaticLongField(jenv, ptr->klass, pf->id, jv.j);
2824
+ }
2825
+ else
2826
+ {
2827
+ (*jenv)->SetLongField(jenv, ptr->obj, pf->id, jv.j);
2828
+ }
2829
+ break;
2830
+ case 'I':
2831
+ if (pf->static_field)
2832
+ {
2833
+ (*jenv)->SetStaticIntField(jenv, ptr->klass, pf->id, jv.i);
2834
+ }
2835
+ else
2836
+ {
2837
+ (*jenv)->SetIntField(jenv, ptr->obj, pf->id, jv.i);
2838
+ }
2839
+ break;
2840
+ default:
2841
+ if (pf->static_field)
2842
+ {
2843
+ (*jenv)->SetStaticObjectField(jenv, ptr->klass, pf->id, jv.l);
2844
+ }
2845
+ else
2846
+ {
2847
+ (*jenv)->SetObjectField(jenv, ptr->obj, pf->id, jv.l);
2848
+ }
2849
+ break;
2850
+ }
2851
+ pf->arg_convert(jenv, val, &jv, pf->field_signature, 1);
2852
+ }
2853
+
2854
+ static VALUE invoke(JNIEnv* jenv, struct cls_method* pm, struct jvi_data* ptr,
2855
+ int argc, VALUE* argv, const char* sig)
2856
+ {
2857
+ int i, found;
2858
+ jvalue jv;
2859
+ jvalue* args;
2860
+ char* psig;
2861
+ struct cls_method* orgpm = pm;
2862
+
2863
+ if (rb_block_given_p())
2864
+ {
2865
+ VALUE* pargs = ALLOCA_N(VALUE, argc + 1);
2866
+ memcpy(pargs, argv, argc * sizeof(VALUE));
2867
+ *(pargs + argc) = rb_block_proc();
2868
+ ++argc;
2869
+ argv = pargs;
2870
+ }
2871
+
2872
+ for (found = 0; pm; pm = pm->next)
2873
+ {
2874
+ if (argc == pm->basic.arg_count)
2875
+ {
2876
+ if (sig && pm->basic.method_signature)
2877
+ {
2878
+ if (!strcmp(sig, pm->basic.method_signature))
2879
+ {
2880
+ found = 1;
2881
+ break;
2882
+ }
2883
+ }
2884
+ else
2885
+ {
2886
+ psig = pm->basic.method_signature;
2887
+ found = 1;
2888
+ for (i = 0; i < argc; i++)
2889
+ {
2890
+ if (!check_rtype(jenv, argv + i, psig))
2891
+ {
2892
+ found = 0;
2893
+ break;
2894
+ }
2895
+ psig = next_sig(psig);
2896
+ }
2897
+ if (found) break;
2898
+ }
2899
+ }
2900
+ }
2901
+ if (!found)
2902
+ {
2903
+ const char* tname = rb_id2name(orgpm->name);
2904
+ if (sig)
2905
+ {
2906
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s(\'%s\')'", tname, sig);
2907
+ }
2908
+ else
2909
+ {
2910
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s'", tname);
2911
+ }
2912
+ }
2913
+ args = (argc) ? ALLOCA_N(jvalue, argc) : NULL;
2914
+ psig = pm->basic.method_signature;
2915
+ for (i = 0; i < argc; i++)
2916
+ {
2917
+ R2J pr2j = *(pm->basic.arg_convert + i);
2918
+ pr2j(jenv, argv[i], args + i, psig, 0);
2919
+ psig = next_sig(psig);
2920
+ }
2921
+ switch (pm->basic.result_signature)
2922
+ {
2923
+ case 'D':
2924
+ {
2925
+ INVOKEAD voked = *(INVOKEAD*)(((char*)*jenv) + pm->method);
2926
+ jv.d = voked(jenv, ptr->obj, pm->basic.id, args);
2927
+ }
2928
+ break;
2929
+ case 'Z':
2930
+ case 'B':
2931
+ {
2932
+ INVOKEAZ vokez = *(INVOKEAZ*)(((char*)*jenv) + pm->method);
2933
+ jv.z = vokez(jenv, ptr->obj, pm->basic.id, args);
2934
+ }
2935
+ break;
2936
+ case 'F':
2937
+ {
2938
+ INVOKEAF vokef = *(INVOKEAF*)(((char*)*jenv) + pm->method);
2939
+ jv.f = vokef(jenv, ptr->obj, pm->basic.id, args);
2940
+ }
2941
+ break;
2942
+ case 'C':
2943
+ case 'S':
2944
+ {
2945
+ INVOKEAS vokes = *(INVOKEAS*)(((char*)*jenv) + pm->method);
2946
+ jv.s = vokes(jenv, ptr->obj, pm->basic.id, args);
2947
+ }
2948
+ break;
2949
+ #if HAVE_LONG_LONG
2950
+ case 'J':
2951
+ {
2952
+ INVOKEAL vokel = *(INVOKEAL*)(((char*)*jenv) + pm->method);
2953
+ jv.j = vokel(jenv, ptr->obj, pm->basic.id, args);
2954
+ }
2955
+ break;
2956
+ #endif
2957
+ default:
2958
+ {
2959
+ INVOKEA voke = *(INVOKEA*)(((char*)*jenv) + pm->method);
2960
+ jv.l = voke(jenv, ptr->obj, pm->basic.id, args);
2961
+ }
2962
+ break;
2963
+ }
2964
+ rjb_check_exception(jenv, 1);
2965
+ psig = pm->basic.method_signature;
2966
+ for (i = 0; i < argc; i++)
2967
+ {
2968
+ R2J pr2j = *(pm->basic.arg_convert + i);
2969
+ pr2j(jenv, argv[i], args + i, psig, 1);
2970
+ psig = next_sig(psig);
2971
+ }
2972
+ if (pm->basic.result_arraydepth)
2973
+ {
2974
+ return ja2r(pm->result_convert, jenv, jv, pm->basic.result_arraydepth);
2975
+ }
2976
+ else
2977
+ {
2978
+ return pm->result_convert(jenv, jv);
2979
+ }
2980
+ }
2981
+
2982
+ /*
2983
+ * Object invocation
2984
+ */
2985
+ static VALUE invoke_by_instance(ID rmid, int argc, VALUE* argv,
2986
+ struct jvi_data* ptr, char* sig)
2987
+ {
2988
+ VALUE ret = Qnil;
2989
+ JNIEnv* jenv = rjb_attach_current_thread();
2990
+ struct cls_field* pf;
2991
+ struct cls_method* pm;
2992
+ const char* tname = rb_id2name(rmid);
2993
+ if (argc == 0 && st_lookup(ptr->fields, rmid, (st_data_t*)&pf))
2994
+ {
2995
+ ret = getter(jenv, pf, ptr);
2996
+ }
2997
+ else
2998
+ {
2999
+ if (argc == 1 && *(tname + strlen(tname) - 1) == '=')
3000
+ {
3001
+ char* fname = ALLOCA_N(char, strlen(tname) + 1);
3002
+ strcpy(fname, tname);
3003
+ fname[strlen(tname) - 1] = '\0';
3004
+ if (st_lookup(ptr->fields, rb_intern(fname), (st_data_t*)&pf))
3005
+ {
3006
+ setter(jenv, pf, ptr, *argv);
3007
+ return ret;
3008
+ }
3009
+ /* fall through for the setter alias name */
3010
+ }
3011
+ if (st_lookup(ptr->methods, rmid, (st_data_t*)&pm))
3012
+ {
3013
+ ret = invoke(jenv, pm, ptr, argc, argv, sig);
3014
+ }
3015
+ else
3016
+ {
3017
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s'", tname);
3018
+ }
3019
+ }
3020
+ return ret;
3021
+ }
3022
+
3023
+ static VALUE get_signature(int* argc, VALUE* argv, VALUE* rmid)
3024
+ {
3025
+ VALUE vsig;
3026
+ rb_scan_args(*argc, argv, "1*", rmid, &vsig);
3027
+ if (*argc == 1)
3028
+ {
3029
+ ++*argc;
3030
+ vsig = Qnil;
3031
+ }
3032
+ else
3033
+ {
3034
+ vsig = *(argv + 1);
3035
+ }
3036
+ return vsig;
3037
+ }
3038
+
3039
+ static VALUE rjb_i_invoke(int argc, VALUE* argv, VALUE self)
3040
+ {
3041
+ VALUE vsig, rmid;
3042
+ char* sig;
3043
+ struct jvi_data* ptr;
3044
+
3045
+ vsig = get_signature(&argc, argv, &rmid);
3046
+ rmid = rb_to_id(rmid);
3047
+ sig = NIL_P(vsig) ? NULL : StringValueCStr(vsig);
3048
+ Data_Get_Struct(self, struct jvi_data, ptr);
3049
+
3050
+ return invoke_by_instance(rmid, argc - 2, argv + 2, ptr, sig);
3051
+ }
3052
+
3053
+ static VALUE rjb_i_missing(int argc, VALUE* argv, VALUE self)
3054
+ {
3055
+ struct jvi_data* ptr;
3056
+ ID rmid = rb_to_id(argv[0]);
3057
+
3058
+ Data_Get_Struct(self, struct jvi_data, ptr);
3059
+
3060
+ return invoke_by_instance(rmid, argc -1, argv + 1, ptr, NULL);
3061
+ }
3062
+
3063
+ /*
3064
+ * Class invocation (first static method, then instance method)
3065
+ */
3066
+ static VALUE invoke_by_class(ID rmid, int argc, VALUE* argv,
3067
+ struct jv_data* ptr, char* sig)
3068
+ {
3069
+ VALUE ret = Qnil;
3070
+ struct jv_data* clsptr;
3071
+ struct cls_field* pf;
3072
+ struct cls_method* pm;
3073
+ const char* tname = rb_id2name(rmid);
3074
+ JNIEnv* jenv = rjb_attach_current_thread();
3075
+
3076
+ Data_Get_Struct(jklass, struct jv_data, clsptr);
3077
+ if (argc == 0 && st_lookup(ptr->idata.fields, rmid, (st_data_t*)&pf))
3078
+ {
3079
+ if (!pf->static_field)
3080
+ {
3081
+ rb_raise(rb_eRuntimeError, "instance field `%s' for class", tname);
3082
+ }
3083
+ ret = getter(jenv, pf, &ptr->idata);
3084
+ }
3085
+ else if (argc == 1 && *(tname + strlen(tname) - 1) == '=')
3086
+ {
3087
+ char* fname = ALLOCA_N(char, strlen(tname) + 1);
3088
+ strcpy(fname, tname);
3089
+ fname[strlen(tname) - 1] = '\0';
3090
+ if (st_lookup(ptr->idata.fields, rb_intern(fname), (st_data_t*)&pf))
3091
+ {
3092
+ if (!pf->static_field)
3093
+ {
3094
+ rb_raise(rb_eRuntimeError, "instance field `%s' for class", fname);
3095
+ }
3096
+ setter(jenv, pf, &ptr->idata, *argv);
3097
+ }
3098
+ else
3099
+ {
3100
+ rb_raise(rb_eRuntimeError, "Fail: unknown field name `%s'", fname);
3101
+ }
3102
+ }
3103
+ else if (st_lookup(ptr->static_methods, rmid, (st_data_t*)&pm))
3104
+ {
3105
+ ret = invoke(jenv, pm, &ptr->idata, argc, argv, sig);
3106
+ }
3107
+ else if (st_lookup(clsptr->idata.methods, rmid, (st_data_t*)&pm))
3108
+ {
3109
+ ret = invoke(jenv, pm, &ptr->idata, argc, argv, sig);
3110
+ }
3111
+ else
3112
+ {
3113
+ if (st_lookup(ptr->idata.methods, rmid, (st_data_t*)&pm))
3114
+ {
3115
+ rb_raise(rb_eRuntimeError, "instance method `%s' for class", tname);
3116
+ }
3117
+ else
3118
+ {
3119
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s'", tname);
3120
+ }
3121
+ }
3122
+
3123
+ return ret;
3124
+ }
3125
+
3126
+ static VALUE rjb_invoke(int argc, VALUE* argv, VALUE self)
3127
+ {
3128
+ VALUE vsig, rmid;
3129
+ char* sig;
3130
+ struct jv_data* ptr;
3131
+
3132
+ vsig = get_signature(&argc, argv, &rmid);
3133
+ rmid = rb_to_id(rmid);
3134
+ sig = NIL_P(vsig) ? NULL : StringValueCStr(vsig);
3135
+ Data_Get_Struct(self, struct jv_data, ptr);
3136
+
3137
+ return invoke_by_class(rmid, argc - 2, argv + 2, ptr, sig);
3138
+ }
3139
+
3140
+ static VALUE find_const(VALUE pv)
3141
+ {
3142
+ VALUE* p = (VALUE*)pv;
3143
+ return rb_const_get(*p, (ID)*(p + 1));
3144
+ }
3145
+
3146
+ static VALUE rjb_missing(int argc, VALUE* argv, VALUE self)
3147
+ {
3148
+ struct jv_data* ptr;
3149
+ ID rmid = rb_to_id(argv[0]);
3150
+ const char* rmname = rb_id2name(rmid);
3151
+
3152
+ if (isupper(*rmname))
3153
+ {
3154
+ VALUE r, args[2];
3155
+ int state = 0;
3156
+ args[0] = rb_obj_class(self);
3157
+ args[1] = rmid;
3158
+ r = rb_protect(find_const, (VALUE)args, &state);
3159
+ if (!state)
3160
+ {
3161
+ return r;
3162
+ }
3163
+ }
3164
+
3165
+ Data_Get_Struct(self, struct jv_data, ptr);
3166
+ return invoke_by_class(rmid, argc - 1, argv + 1, ptr, NULL);
3167
+ }
3168
+
3169
+ /*
3170
+ * Class#forName entry.
3171
+ */
3172
+ static VALUE rjb_class_forname(int argc, VALUE* argv, VALUE self)
3173
+ {
3174
+ if (argc == 1)
3175
+ {
3176
+ return rjb_s_import(self, *argv);
3177
+ }
3178
+ else
3179
+ {
3180
+ struct jv_data* ptr;
3181
+ ID rmid = rb_intern("forName");
3182
+ Data_Get_Struct(self, struct jv_data, ptr);
3183
+ return invoke_by_class(rmid, argc, argv, ptr, NULL);
3184
+ }
3185
+ }
3186
+
3187
+ /*
3188
+ * Class initializer called by Ruby while requiring this library
3189
+ */
3190
+ void Init_rjbcore()
3191
+ {
3192
+ #if RJB_RUBY_VERSION_CODE < 190
3193
+ #if defined(RUBINIUS)
3194
+ rb_require("iconv");
3195
+ #else
3196
+ rb_protect((VALUE(*)(VALUE))rb_require, (VALUE)"iconv", NULL);
3197
+ #endif
3198
+ #endif
3199
+ rjb_loaded_classes = rb_hash_new();
3200
+ #ifndef RUBINIUS
3201
+ OBJ_FREEZE(rjb_loaded_classes);
3202
+ #endif
3203
+ rb_global_variable(&rjb_loaded_classes);
3204
+ proxies = rb_ary_new();
3205
+ rb_global_variable(&proxies);
3206
+ user_initialize = rb_intern(USER_INITIALIZE);
3207
+ initialize_proxy = rb_intern("initialize_proxy");
3208
+
3209
+ rjb = rb_define_module("Rjb");
3210
+ rb_define_module_function(rjb, "load", rjb_s_load, -1);
3211
+ rb_define_module_function(rjb, "unload", rjb_s_unload, -1);
3212
+ rb_define_module_function(rjb, "loaded?", rjb_s_loaded, 0);
3213
+ rb_define_module_function(rjb, "import", rjb_s_import, 1);
3214
+ rb_define_module_function(rjb, "bind", rjb_s_bind, 2);
3215
+ rb_define_module_function(rjb, "unbind", rjb_s_unbind, 1);
3216
+ rb_define_module_function(rjb, "classes", rjb_s_classes, 0);
3217
+ rb_define_module_function(rjb, "throw", rjb_s_throw, -1);
3218
+ rb_define_module_function(rjb, "primitive_conversion=", rjb_s_set_pconversion, 1);
3219
+ rb_define_module_function(rjb, "primitive_conversion", rjb_s_get_pconversion, 0);
3220
+ rb_define_module_function(rjb, "add_classpath", rjb_s_add_classpath, 1);
3221
+ rb_define_module_function(rjb, "add_jar", rjb_s_add_jar, 1);
3222
+ rb_define_alias(rjb, "add_jars", "add_jar");
3223
+ rb_define_module_function(rjb, "urls", rjb_s_urls, 0);
3224
+ rb_define_const(rjb, "VERSION", rb_str_new2(RJB_VERSION));
3225
+ rb_define_class_variable(rjb, "@@classpath", rb_ary_new());
3226
+ cvar_classpath = rb_intern("@@classpath");
3227
+
3228
+ /* Java class object */
3229
+ rjbc = CLASS_NEW(rb_cObject, "Rjb_JavaClass");
3230
+ rb_gc_register_address(&rjbc);
3231
+ rb_define_method(rjbc, "method_missing", rjb_missing, -1);
3232
+ rb_define_method(rjbc, "impl", rjb_s_impl, 0);
3233
+ rb_define_method(rjbc, "_invoke", rjb_invoke, -1);
3234
+ rb_define_method(rjbc, "_classname", rjb_i_class, 0);
3235
+
3236
+ /* Java instance object */
3237
+ rjbi = CLASS_NEW(rb_cObject, "Rjb_JavaProxy");
3238
+ rb_gc_register_address(&rjbi);
3239
+ rb_define_method(rjbi, "method_missing", rjb_i_missing, -1);
3240
+ rb_define_method(rjbi, "_invoke", rjb_i_invoke, -1);
3241
+ rb_define_method(rjbi, "_classname", rjb_i_class, 0);
3242
+ rb_define_method(rjbi, "_prepare_proxy", rjb_i_prepare_proxy, 0);
3243
+ rb_define_alias(rjbi, "include", "extend");
3244
+
3245
+ /* Ruby-Java Bridge object */
3246
+ rjbb = CLASS_NEW(rb_cObject, "Rjb_JavaBridge");
3247
+ rb_gc_register_address(&rjbb);
3248
+
3249
+ /* anonymous interface object */
3250
+ rjba = CLASS_NEW(rb_cObject, "Rjb_AnonymousClass");
3251
+ rb_gc_register_address(&rjba);
3252
+ rb_define_method(rjba, "initialize", rjb_a_initialize, 1);
3253
+ rb_define_method(rjba, "method_missing", rjb_a_missing, -1);
3254
+ anonymousblock = rb_intern("@anon_block");
3255
+ id_call = rb_intern("call");
3256
+ }
3257
+
3258
+ VALUE rjb_safe_funcall(VALUE args)
3259
+ {
3260
+ VALUE* argp = (VALUE*)args;
3261
+ return rb_funcall2(*argp, *(argp + 1), (int)*(argp + 2), argp + 3);
3262
+ }
3263
+
3264
+ /**
3265
+ Entry point from JavaVM through java.reflect.Proxy
3266
+ */
3267
+ JNIEXPORT jobject JNICALL Java_jp_co_infoseek_hp_arton_rjb_RBridge_call
3268
+ (JNIEnv * jenv, jobject bridge, jstring name, jobject proxy, jobjectArray args)
3269
+ {
3270
+ int i;
3271
+ jvalue j;
3272
+ memset(&j, 0, sizeof(j));
3273
+ for (i = 0; i < RARRAY_LEN(proxies); i++)
3274
+ {
3275
+ struct rj_bridge* ptr;
3276
+ VALUE val = RARRAY_PTR(proxies)[i];
3277
+ Data_Get_Struct(val, struct rj_bridge, ptr);
3278
+ if ((*jenv)->IsSameObject(jenv, proxy, ptr->proxy))
3279
+ {
3280
+ int sstat;
3281
+ VALUE result;
3282
+ VALUE* argv = NULL;
3283
+ int argc = 3;
3284
+ ID id = rb_to_id(jstring2val(jenv, name));
3285
+ if (args)
3286
+ {
3287
+ int i;
3288
+ jsize js = (*jenv)->GetArrayLength(jenv, args);
3289
+ argc += (int)js;
3290
+ argv = ALLOCA_N(VALUE, argc);
3291
+ memset(argv, 0, sizeof(VALUE*) * argc);
3292
+ for (i = 3; i < argc; i++)
3293
+ {
3294
+ jobject f = (*jenv)->GetObjectArrayElement(jenv, args, i - 3);
3295
+ /* f will be release in jv2rv_withprim */
3296
+ *(argv + i) = jv2rv_withprim(jenv, f);
3297
+ }
3298
+ }
3299
+ else
3300
+ {
3301
+ argv = ALLOCA_N(VALUE, argc + 1);
3302
+ memset(argv, 0, sizeof(VALUE*) * (argc + 1));
3303
+ }
3304
+ *argv = ptr->wrapped;
3305
+ *(argv + 1) = id;
3306
+ *(argv + 2) = argc - 3;
3307
+ result = rb_protect(rjb_safe_funcall, (VALUE)argv, &sstat);
3308
+ rv2jobject(jenv, result, &j, NULL, 0);
3309
+ /* I can't delete this object... */
3310
+ break;
3311
+ }
3312
+ }
3313
+ return j.l;
3314
+ }