a6bdee48f3
Reviewed-by: kevinw, kbarrett, dholmes
211 lines
6.5 KiB
C++
211 lines
6.5 KiB
C++
/*
|
|
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
#ifndef __CallHelper_hpp__
|
|
#define __CallHelper_hpp__
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <jni.h>
|
|
#undef NDEBUG
|
|
#include <assert.h>
|
|
#include <string>
|
|
#include <algorithm>
|
|
|
|
/*
|
|
* basis of classes to provide a bunch of checking in native calls to java
|
|
*/
|
|
class CallHelper {
|
|
public:
|
|
CallHelper(JNIEnv* e, const std::string& cname, const std::string& mname, const std::string& sig) :
|
|
classname(cname), method(mname), signature(sig), m(nullptr), env(e) {
|
|
c = env->FindClass(classname.c_str());
|
|
assert (c != nullptr);
|
|
}
|
|
|
|
protected:
|
|
|
|
// emit a message with the call made appended to the message
|
|
void emitErrorMessage(const std::string& msg) {
|
|
std::string nm = classname;
|
|
std::replace(nm.begin(), nm.end(), '/', '.');
|
|
::fprintf(stderr, "ERROR: %s::%s, %s\n", nm.c_str(), method.c_str(), msg.c_str());
|
|
}
|
|
|
|
// check the given object which is expected to be null
|
|
void checkReturnNull(jobject obj) {
|
|
if (obj != nullptr) {
|
|
emitErrorMessage("Null return expected");
|
|
::exit(-1);
|
|
}
|
|
}
|
|
|
|
// check the given object which is expected to NOT be null
|
|
void checkReturnNotNull(jobject obj) {
|
|
if (obj == nullptr) {
|
|
emitErrorMessage("Non-Null return expected");
|
|
::exit(-1);
|
|
}
|
|
}
|
|
|
|
// check if any unexpected exceptions were thrown
|
|
void checkException() {
|
|
if (env->ExceptionOccurred() != nullptr) {
|
|
emitErrorMessage("Exception was thrown");
|
|
env->ExceptionDescribe();
|
|
::exit(-1);
|
|
}
|
|
}
|
|
|
|
// check if an expected exception was thrown
|
|
void checkExpectedExceptionThrown(const std::string& exception) {
|
|
jclass expected = env->FindClass(exception.c_str());
|
|
assert(expected != nullptr);
|
|
jthrowable t = env->ExceptionOccurred();
|
|
if (env->IsInstanceOf(t, expected) == JNI_FALSE) {
|
|
emitErrorMessage("Didn't get the expected " + exception);
|
|
::exit(-1);
|
|
}
|
|
env->ExceptionClear();
|
|
}
|
|
|
|
protected:
|
|
std::string classname;
|
|
std::string method;
|
|
std::string signature;
|
|
jclass c;
|
|
jmethodID m;
|
|
JNIEnv* env;
|
|
};
|
|
|
|
/*
|
|
* support for making checked calls on instances of an object
|
|
*/
|
|
class InstanceCall : public CallHelper {
|
|
public:
|
|
InstanceCall(JNIEnv* e, const std::string& cname, const std::string& mname, const std::string& sig)
|
|
: CallHelper(e, cname, mname, sig) {
|
|
|
|
m = env->GetMethodID(c, method.c_str(), signature.c_str());
|
|
assert(m != nullptr);
|
|
}
|
|
|
|
// call on the given object, checking for exceptions and that the return is not null
|
|
jobject callReturnNotNull(jobject obj) {
|
|
jobject robj = call(obj);
|
|
checkReturnNotNull(robj);
|
|
return robj;
|
|
}
|
|
|
|
// call on the given object with an argument,
|
|
// checking for exceptions and that the return is not null
|
|
jobject callReturnNotNull(jobject obj, jobject arg) {
|
|
jobject robj = call(obj, arg);
|
|
checkReturnNotNull(robj);
|
|
return robj;
|
|
}
|
|
|
|
// call on the given object, checking for exceptions and that the return is null
|
|
jobject callReturnIsNull(jobject obj) {
|
|
jobject robj = call(obj);
|
|
checkReturnNull(robj);
|
|
return robj;
|
|
}
|
|
|
|
// call on the given object with an argument,
|
|
// checking for exceptions and that the return is null
|
|
jobject callReturnIsNull(jobject obj, jobject arg) {
|
|
jobject robj = call(obj, arg);
|
|
checkReturnNull(robj);
|
|
return robj;
|
|
}
|
|
|
|
// call a void method checking if exceptions were thrown
|
|
void callVoidMethod(jobject obj) {
|
|
env->CallVoidMethod(obj, m);
|
|
checkException();
|
|
}
|
|
|
|
jobject call(jobject obj) {
|
|
jobject robj = env->CallObjectMethod(obj, m);
|
|
checkException();
|
|
return robj;
|
|
}
|
|
|
|
jobject call(jobject obj, jobject arg) {
|
|
jobject robj = env->CallObjectMethod(obj, m, arg);
|
|
checkException();
|
|
return robj;
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
* support for making checked static calls
|
|
*/
|
|
class StaticCall : public CallHelper {
|
|
public:
|
|
StaticCall(JNIEnv* e, const std::string& cname, const std::string& mname, const std::string& sig)
|
|
: CallHelper(e, cname, mname, sig) {
|
|
|
|
m = env->GetStaticMethodID(c, method.c_str(), signature.c_str());
|
|
assert(m != nullptr);
|
|
}
|
|
|
|
// call a method returning an object checking for exceptions and
|
|
// the return value is not null.
|
|
jobject callReturnNotNull(jobject arg) {
|
|
jobject robj = env->CallStaticObjectMethod(c, m, arg);
|
|
checkException();
|
|
checkReturnNotNull(robj);
|
|
return robj;
|
|
}
|
|
|
|
// call a void method checking if any exceptions thrown
|
|
void callVoidMethod() {
|
|
env->CallStaticVoidMethod(c, m);
|
|
checkException();
|
|
}
|
|
|
|
// call method returning boolean that is expected to throw the
|
|
// given exception
|
|
void callBooleanMethodWithException(const std::string& exception) {
|
|
env->CallStaticBooleanMethod(c, m);
|
|
checkExpectedExceptionThrown(exception);
|
|
}
|
|
|
|
// call method returning an object that is expected to throw the
|
|
// given exception
|
|
void callObjectMethodWithException(const std::string& exception) {
|
|
env->CallStaticObjectMethod(c, m);
|
|
checkExpectedExceptionThrown(exception);
|
|
}
|
|
};
|
|
|
|
void emitErrorMessageAndExit(const std::string& msg) {
|
|
::fprintf(stderr, "ERROR: %s\n", msg.c_str());
|
|
::exit(-1);
|
|
}
|
|
|
|
#endif // __CallHelper_hpp__
|
|
|