|
1 /* |
|
2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 */ |
|
23 |
|
24 #include <jni.h> |
|
25 |
|
26 // boolean flag for static versus non-static |
|
27 #define STATIC 1 |
|
28 #define NON_STATIC 0 |
|
29 |
|
30 // Helper methods to get class/method/field IDs |
|
31 |
|
32 static void getClassID(JNIEnv *env, |
|
33 jstring defining_class_name, |
|
34 jclass* clazz) { |
|
35 const char* name = (*env)->GetStringUTFChars(env, defining_class_name, NULL); |
|
36 if (name != NULL) { |
|
37 *clazz = (*env)->FindClass(env, name); |
|
38 (*env)->ReleaseStringUTFChars(env, defining_class_name, name); |
|
39 } |
|
40 } |
|
41 |
|
42 static void getClassAndMethodID(JNIEnv *env, |
|
43 int is_static, |
|
44 jstring defining_class_name, |
|
45 jstring method_name, |
|
46 const char* sig, |
|
47 jmethodID* m_id, jclass* clazz) { |
|
48 getClassID(env, defining_class_name, clazz); |
|
49 if (*clazz != NULL) { |
|
50 const char* name = (*env)->GetStringUTFChars(env, method_name, NULL); |
|
51 if (name != NULL) { |
|
52 if (is_static) { |
|
53 *m_id = (*env)->GetStaticMethodID(env, *clazz, name, sig); |
|
54 } else { |
|
55 *m_id = (*env)->GetMethodID(env, *clazz, name, sig); |
|
56 } |
|
57 (*env)->ReleaseStringUTFChars(env, method_name, name); |
|
58 } |
|
59 } |
|
60 } |
|
61 |
|
62 static void getClassAndFieldID(JNIEnv *env, |
|
63 int is_static, |
|
64 jstring defining_class_name, |
|
65 jstring field_name, |
|
66 const char* sig, |
|
67 jfieldID* m_id, jclass* clazz) { |
|
68 getClassID(env, defining_class_name, clazz); |
|
69 if (*clazz != NULL) { |
|
70 const char* name = (*env)->GetStringUTFChars(env, field_name, NULL); |
|
71 if (name != NULL) { |
|
72 if (is_static) { |
|
73 *m_id = (*env)->GetStaticFieldID(env, *clazz, name, sig); |
|
74 } else { |
|
75 *m_id = (*env)->GetFieldID(env, *clazz, name, sig); |
|
76 } |
|
77 (*env)->ReleaseStringUTFChars(env, field_name, name); |
|
78 } |
|
79 } |
|
80 } |
|
81 |
|
82 JNIEXPORT void JNICALL |
|
83 Java_NestmatesJNI_callVoidVoid(JNIEnv *env, jclass unused, |
|
84 jobject target, |
|
85 jstring defining_class_name, |
|
86 jstring method_name, |
|
87 jboolean virtual) { |
|
88 |
|
89 // Lookup "void method_name()" in defining_class_name, and if it exists |
|
90 // call target.method_name() using a virtual or non-virtual invocation |
|
91 |
|
92 jmethodID m_id = NULL; |
|
93 jclass clazz = NULL; |
|
94 getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name, |
|
95 "()V", &m_id, &clazz); |
|
96 if (m_id != NULL && clazz != NULL) { |
|
97 if (!virtual) { |
|
98 (*env)->CallNonvirtualVoidMethod(env, target, clazz, m_id); |
|
99 } else { |
|
100 (*env)->CallVoidMethod(env, target, m_id); |
|
101 } |
|
102 } |
|
103 } |
|
104 |
|
105 JNIEXPORT jobject JNICALL |
|
106 Java_NestmatesJNI_callStringVoid(JNIEnv *env, jclass unused, |
|
107 jobject target, |
|
108 jstring defining_class_name, |
|
109 jstring method_name, |
|
110 jboolean virtual) { |
|
111 |
|
112 // Lookup "String method_name()" in defining_class_name, and if it exists |
|
113 // call target.method_name() using a virtual or non-virtual invocation |
|
114 |
|
115 jmethodID m_id = NULL; |
|
116 jclass clazz = NULL; |
|
117 getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name, |
|
118 "()Ljava/lang/String;", &m_id, &clazz); |
|
119 if (m_id != NULL && clazz != NULL) { |
|
120 if (!virtual) { |
|
121 return (*env)->CallNonvirtualObjectMethod(env, target, clazz, m_id); |
|
122 } else { |
|
123 return (*env)->CallObjectMethod(env, target, m_id); |
|
124 } |
|
125 } |
|
126 return NULL; |
|
127 } |
|
128 |
|
129 JNIEXPORT jobject JNICALL |
|
130 Java_NestmatesJNI_newInstance0(JNIEnv *env, jclass unused, |
|
131 jstring defining_class_name, |
|
132 jstring method_name, |
|
133 jstring sig, |
|
134 jobject outerThis) { |
|
135 |
|
136 // Lookup the no-user-arg constructor in defining_class_name using sig, |
|
137 // and use it to create an instance of the class, and return it. For |
|
138 // inner classes we need an outerThis reference to pass to the constructor. |
|
139 |
|
140 jmethodID m_id = NULL; |
|
141 jclass clazz = NULL; |
|
142 const char* _sig = (*env)->GetStringUTFChars(env, sig, NULL); |
|
143 getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name, |
|
144 _sig, &m_id, &clazz); |
|
145 (*env)->ReleaseStringUTFChars(env, sig, _sig); |
|
146 if (m_id != NULL && clazz != NULL) { |
|
147 return (*env)->NewObject(env, clazz, m_id, outerThis); |
|
148 } |
|
149 return NULL; |
|
150 } |
|
151 |
|
152 JNIEXPORT void JNICALL |
|
153 Java_NestmatesJNI_callStaticVoidVoid(JNIEnv *env, jclass unused, |
|
154 jstring defining_class_name, |
|
155 jstring method_name) { |
|
156 |
|
157 // Lookup "static void method_name()" in defining_class_name, and if it exists |
|
158 // invoke it. |
|
159 |
|
160 jmethodID m_id = NULL; |
|
161 jclass clazz = NULL; |
|
162 getClassAndMethodID(env, STATIC, defining_class_name, method_name, |
|
163 "()V", &m_id, &clazz); |
|
164 if (m_id != NULL && clazz != NULL) { |
|
165 (*env)->CallStaticVoidMethod(env, clazz, m_id); |
|
166 } |
|
167 } |
|
168 |
|
169 JNIEXPORT jint JNICALL |
|
170 Java_NestmatesJNI_getIntField(JNIEnv *env, jclass unused, |
|
171 jobject target, |
|
172 jstring defining_class_name, |
|
173 jstring field_name) { |
|
174 |
|
175 // Lookup field field_name in defining_class_name, and if it exists |
|
176 // return its value. |
|
177 |
|
178 jfieldID f_id = NULL; |
|
179 jclass clazz = NULL; |
|
180 getClassAndFieldID(env, NON_STATIC, defining_class_name, field_name, |
|
181 "I", &f_id, &clazz); |
|
182 if (f_id != NULL && clazz != NULL) { |
|
183 return (*env)->GetIntField(env, target, f_id); |
|
184 } |
|
185 return -1; |
|
186 } |
|
187 |
|
188 JNIEXPORT void JNICALL |
|
189 Java_NestmatesJNI_setIntField(JNIEnv *env, jclass unused, |
|
190 jobject target, |
|
191 jstring defining_class_name, |
|
192 jstring field_name, |
|
193 jint newVal) { |
|
194 |
|
195 // Lookup field field_name in defining_class_name, and if it exists |
|
196 // set it to newVal. |
|
197 |
|
198 jfieldID f_id = NULL; |
|
199 jclass clazz = NULL; |
|
200 getClassAndFieldID(env, NON_STATIC, defining_class_name, field_name, |
|
201 "I", &f_id, &clazz); |
|
202 if (f_id != NULL && clazz != NULL) { |
|
203 (*env)->SetIntField(env, target, f_id, newVal); |
|
204 } |
|
205 } |
|
206 |
|
207 JNIEXPORT jint JNICALL |
|
208 Java_NestmatesJNI_getStaticIntField(JNIEnv *env, jclass unused, |
|
209 jstring defining_class_name, |
|
210 jstring field_name) { |
|
211 |
|
212 // Lookup field field_name in defining_class_name, and if it exists |
|
213 // return its value. |
|
214 |
|
215 jfieldID f_id = NULL; |
|
216 jclass clazz = NULL; |
|
217 getClassAndFieldID(env, STATIC, defining_class_name, field_name, |
|
218 "I", &f_id, &clazz); |
|
219 if (f_id != NULL && clazz != NULL) { |
|
220 return (*env)->GetStaticIntField(env, clazz, f_id); |
|
221 } |
|
222 return -1; |
|
223 } |
|
224 |
|
225 JNIEXPORT void JNICALL |
|
226 Java_NestmatesJNI_setStaticIntField(JNIEnv *env, jclass unused, |
|
227 jstring defining_class_name, |
|
228 jstring field_name, |
|
229 jint newVal) { |
|
230 |
|
231 // Lookup field field_name in defining_class_name, and if it exists |
|
232 // set it to newVal. |
|
233 |
|
234 jfieldID f_id = NULL; |
|
235 jclass clazz = NULL; |
|
236 getClassAndFieldID(env, STATIC, defining_class_name, field_name, |
|
237 "I", &f_id, &clazz); |
|
238 if (f_id != NULL && clazz != NULL) { |
|
239 (*env)->SetStaticIntField(env, clazz, f_id, newVal); |
|
240 } |
|
241 } |