Skip to content
This repository was archived by the owner on Mar 8, 2020. It is now read-only.

Commit 5b81fbb

Browse files
authored
Merge pull request #91 from bzz/load-impl
Node.load() implementation
2 parents 2bc2167 + c8091e6 commit 5b81fbb

15 files changed

+833
-94
lines changed

.travis.yml

-11
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ stages:
1818
- name: release
1919
if: tag IS present
2020

21-
2221
jobs:
2322
include:
2423
- name: 'All tests'
2524
stage: test
26-
if: tag IS present # TODO(bzz): enable on PRs as soon as migrated to V2
2725
install: &test_setup_anchor
2826
- docker run --privileged -d -p 9432:9432 --name bblfsh bblfsh/bblfshd
2927
- docker exec -it bblfsh bblfshctl driver install --recommended
@@ -34,15 +32,6 @@ jobs:
3432
after_failure: &failure_logs_anchor
3533
- docker logs bblfsh
3634

37-
- name: 'V2: passing tests' # TODO(#83): remove, after both tests sets converge
38-
install: *test_setup_anchor
39-
script:
40-
- sudo apt-get install -y binutils
41-
- ./sbt assembly
42-
- ./sbt "testOnly *Close* *ClientVersion* *SupportedLanguages* *BblfshClientParseTest"
43-
44-
after_failure: *failure_logs_anchor
45-
4635
- name: 'Cross-compile, release & publish to Sonatype'
4736
stage: release
4837
before_install:

src/main/native/jni_utils.cc

+142-20
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
#include "jni_utils.h"
2+
#include <string>
23

3-
// Class fully qualified names
4-
const char *CLS_NODE = "org/bblfsh/client/v2/Node";
5-
const char *CLS_CTX = "org/bblfsh/client/v2/Context";
6-
7-
extern JavaVM *jvm; // FIXME(bzz): double-check and document
4+
// TODO(bzz): double-check and document. Suggestion and more context at
5+
// https://github.com/bblfsh/client-scala/pull/84#discussion_r288347756
6+
extern JavaVM *jvm;
87

98
JNIEnv *getJNIEnv() {
109
JNIEnv *pEnv = NULL;
@@ -21,38 +20,161 @@ JNIEnv *getJNIEnv() {
2120
return pEnv;
2221
}
2322

23+
const char CLS_NODE[] = "org/bblfsh/client/v2/Node";
24+
const char CLS_CTX[] = "org/bblfsh/client/v2/Context";
25+
const char CLS_OBJ[] = "java/lang/Object";
26+
const char CLS_RE[] = "java/lang/RuntimeException";
27+
const char CLS_JNODE[] = "org/bblfsh/client/v2/JNode";
28+
const char CLS_JNULL[] = "org/bblfsh/client/v2/JNull";
29+
const char CLS_JSTR[] = "org/bblfsh/client/v2/JString";
30+
const char CLS_JINT[] = "org/bblfsh/client/v2/JInt";
31+
const char CLS_JFLT[] = "org/bblfsh/client/v2/JFloat";
32+
const char CLS_JBOOL[] = "org/bblfsh/client/v2/JBool";
33+
const char CLS_JUINT[] = "org/bblfsh/client/v2/JUint";
34+
const char CLS_JARR[] = "org/bblfsh/client/v2/JArray";
35+
const char CLS_JOBJ[] = "org/bblfsh/client/v2/JObject";
36+
37+
const char METHOD_JNODE_KEY_AT[] = "(I)Ljava/lang/String;";
38+
const char METHOD_JNODE_VALUE_AT[] = "(I)Lorg/bblfsh/client/v2/JNode;";
39+
const char METHOD_JOBJ_ADD[] =
40+
"(Ljava/lang/String;Lorg/bblfsh/client/v2/JNode;)Lscala/collection/"
41+
"mutable/Buffer;";
42+
const char METHOD_JARR_ADD[] =
43+
"(Lorg/bblfsh/client/v2/JNode;)Lscala/collection/mutable/Buffer;";
44+
45+
const char METHOD_OBJ_TO_STR[] = "()Ljava/lang/String;";
46+
47+
// TODO(bzz): cache classes&methods in JNI_OnLoad should speed this up
48+
void checkJvmException(std::string msg) {
49+
JNIEnv *env = getJNIEnv();
50+
auto err = env->ExceptionOccurred();
51+
if (err) {
52+
env->ExceptionClear();
53+
54+
auto exceptionCls = env->FindClass(CLS_RE);
55+
if (env->ExceptionCheck()) {
56+
env->ExceptionClear();
57+
env->Throw(env->ExceptionOccurred());
58+
return;
59+
}
60+
61+
jclass cls = env->FindClass(CLS_OBJ);
62+
if (env->ExceptionCheck()) {
63+
env->ExceptionClear();
64+
env->ThrowNew(
65+
exceptionCls,
66+
msg.append(" - failed to find class ").append(CLS_OBJ).data());
67+
return;
68+
}
69+
70+
jmethodID toString = env->GetMethodID(cls, "toString", METHOD_OBJ_TO_STR);
71+
if (env->ExceptionCheck()) {
72+
env->ExceptionClear();
73+
env->ThrowNew(exceptionCls,
74+
msg.append(" - failed to find method toString").data());
75+
return;
76+
}
77+
78+
jstring s = (jstring)env->CallObjectMethod(err, toString);
79+
if (env->ExceptionCheck() || !s) {
80+
env->ThrowNew(exceptionCls,
81+
msg.append(" - failed co call method toString").data());
82+
return;
83+
}
84+
85+
const char *utf = env->GetStringUTFChars(s, 0);
86+
env->ReleaseStringUTFChars(s, utf);
87+
88+
// new RuntimeException(msg.data(), err)
89+
jmethodID initId = env->GetMethodID(
90+
cls, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
91+
jthrowable exception = (jthrowable)env->NewObject(
92+
exceptionCls, initId, msg.append(": ").append(utf).data(), err);
93+
94+
env->Throw(exception);
95+
}
96+
}
97+
2498
jobject NewJavaObject(JNIEnv *env, const char *className, const char *initSign,
2599
...) {
26100
jclass cls = env->FindClass(className);
27-
if (env->ExceptionOccurred() || !cls) {
28-
return NULL;
29-
}
101+
checkJvmException(std::string("failed to find a class ").append(className));
30102

31103
jmethodID initId = env->GetMethodID(cls, "<init>", initSign);
32-
if (env->ExceptionOccurred() || !initId) {
33-
return NULL;
34-
}
104+
checkJvmException(std::string("failed to call a constructor with signature ")
105+
.append(initSign)
106+
.append(" for the class name ")
107+
.append(className));
35108

36109
va_list varargs;
37110
va_start(varargs, initSign);
38111
jobject instance = env->NewObjectV(cls, initId, varargs);
39112
va_end(varargs);
40-
if (env->ExceptionOccurred() || !instance) {
41-
return NULL;
42-
}
113+
checkJvmException(
114+
std::string("failed get varargs for constructor of ").append(className));
43115

44116
return instance;
45117
}
46118

47119
jfieldID getField(JNIEnv *env, jobject obj, const char *name) {
48120
jclass cls = env->GetObjectClass(obj);
49-
if (env->ExceptionOccurred() || !cls) {
50-
return nullptr;
51-
}
121+
checkJvmException("failed get the class of an object");
52122

53123
jfieldID jfid = env->GetFieldID(cls, name, "J");
54-
if (env->ExceptionOccurred() || !jfid) {
55-
return nullptr;
56-
}
124+
checkJvmException(std::string("failed get a field ").append(name));
125+
57126
return jfid;
58127
}
128+
129+
static jmethodID MethodID(JNIEnv *env, const char *method,
130+
const char *signature, const char *className) {
131+
jclass cls = env->FindClass(className);
132+
checkJvmException(std::string("failed to find a class ").append(className));
133+
134+
jmethodID mId = env->GetMethodID(cls, method, signature);
135+
checkJvmException(std::string("failed to get method ")
136+
.append(className)
137+
.append(".")
138+
.append(method));
139+
140+
return mId;
141+
}
142+
143+
jint IntMethod(JNIEnv *env, const char *method, const char *signature,
144+
const char *className, const jobject *object) {
145+
jmethodID mId = MethodID(env, method, signature, className);
146+
checkJvmException(std::string("failed to get method ")
147+
.append(className)
148+
.append(".")
149+
.append(method));
150+
151+
jint res = env->CallIntMethod(*object, mId);
152+
checkJvmException(std::string("failed to call method ")
153+
.append(className)
154+
.append(".")
155+
.append(method)
156+
.append(" using signature ")
157+
.append(signature));
158+
159+
return res;
160+
}
161+
162+
jobject ObjectMethod(JNIEnv *env, const char *method, const char *signature,
163+
const char *className, const jobject *object, ...) {
164+
jmethodID mId = MethodID(env, method, signature, className);
165+
checkJvmException(std::string("failed to get method ")
166+
.append(className)
167+
.append(".")
168+
.append(method));
169+
170+
va_list varargs;
171+
va_start(varargs, object);
172+
jobject res = env->CallObjectMethodV(*object, mId, varargs);
173+
va_end(varargs);
174+
checkJvmException(std::string("failed get varargs for ")
175+
.append(className)
176+
.append(".")
177+
.append(method));
178+
179+
return res;
180+
}

src/main/native/jni_utils.h

+37-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,46 @@
22
#define _Included_org_bblfsh_client_libuast_Libuast_jni_utils
33

44
#include <jni.h>
5+
#include <string>
56

6-
extern const char *CLS_NODE;
7-
extern const char *CLS_CTX;
7+
// Fully qualified Java class names
8+
extern const char CLS_NODE[];
9+
extern const char CLS_CTX[];
10+
extern const char CLS_OBJ[];
11+
extern const char CLS_RE[];
12+
13+
// Fully qualified class names for Bablefish UAST types
14+
extern const char CLS_JNODE[];
15+
extern const char CLS_JNULL[];
16+
extern const char CLS_JSTR[];
17+
extern const char CLS_JINT[];
18+
extern const char CLS_JFLT[];
19+
extern const char CLS_JBOOL[];
20+
extern const char CLS_JUINT[];
21+
extern const char CLS_JARR[];
22+
extern const char CLS_JOBJ[];
23+
24+
// Method signatures
25+
extern const char METHOD_JNODE_KEY_AT[];
26+
extern const char METHOD_JNODE_VALUE_AT[];
27+
extern const char METHOD_JOBJ_ADD[];
28+
extern const char METHOD_JARR_ADD[];
29+
extern const char METHOD_OBJ_TO_STR[];
30+
31+
// Checks though JNI, if there is a pending excption on JVM side.
32+
//
33+
// Throws new RuntimeExpection to JVM in case there is,
34+
// uses the origial one as a cause and the given string as a message.
35+
void checkJvmException(std::string);
836

937
JNIEnv *getJNIEnv();
1038
jobject NewJavaObject(JNIEnv *, const char *, const char *, ...);
1139
jfieldID getField(JNIEnv *env, jobject obj, const char *name);
1240

13-
#endif
41+
jint IntMethod(JNIEnv *, const char *, const char *, const char *,
42+
const jobject *);
43+
44+
jobject ObjectMethod(JNIEnv *, const char *, const char *, const char *,
45+
const jobject *, ...);
46+
47+
#endif

src/main/native/org_bblfsh_client_v2_Context__.h

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)