use std::ffi::CStr;
use crate::{
java,
jvm::JavaObjectExt,
raw::{FieldPtr, MethodPtr},
Jvm, Local, LocalResult,
};
pub fn find_class<'jvm>(
jvm: &mut Jvm<'jvm>,
jni_name: &CStr,
) -> LocalResult<'jvm, Local<'jvm, java::lang::Class>> {
let class: Option<Local<java::lang::Class>> = unsafe {
jvm.env()
.invoke(|env| env.FindClass, |env, f| f(env, jni_name.as_ptr()))
}?;
class.ok_or_else(|| {
crate::Error::JvmInternal(format!(
"failed to find class `{}`",
jni_name.to_string_lossy()
))
})
}
pub fn find_method<'jvm>(
jvm: &mut Jvm<'jvm>,
class: impl AsRef<java::lang::Class>,
jni_name: &CStr,
jni_descriptor: &CStr,
is_static: bool,
) -> LocalResult<'jvm, MethodPtr> {
let class = class.as_ref().as_raw();
let env = jvm.env();
let method = unsafe {
env.invoke_unchecked(
|env| {
if is_static {
env.GetStaticMethodID
} else {
env.GetMethodID
}
},
|env, f| {
f(
env,
class.as_ptr(),
jni_name.as_ptr(),
jni_descriptor.as_ptr(),
)
},
)
};
if let Some(method) = MethodPtr::new(method) {
Ok(method)
} else {
jvm.env().check_exception()?;
Err(crate::Error::JvmInternal(format!(
"failed to find method `{}` with signature `{}`",
jni_name.to_string_lossy(),
jni_descriptor.to_string_lossy(),
)))
}
}
pub fn find_field<'jvm>(
jvm: &mut Jvm<'jvm>,
class: impl AsRef<java::lang::Class>,
jni_name: &CStr,
jni_descriptor: &CStr,
is_static: bool,
) -> LocalResult<'jvm, FieldPtr> {
let class = class.as_ref().as_raw();
let env = jvm.env();
let field = unsafe {
env.invoke_unchecked(
|env| {
if is_static {
env.GetStaticFieldID
} else {
env.GetFieldID
}
},
|env, f| {
f(
env,
class.as_ptr(),
jni_name.as_ptr(),
jni_descriptor.as_ptr(),
)
},
)
};
if let Some(field) = FieldPtr::new(field) {
Ok(field)
} else {
jvm.env().check_exception()?;
Err(crate::Error::JvmInternal(format!(
"failed to find field `{}` with signature `{}`",
jni_name.to_string_lossy(),
jni_descriptor.to_string_lossy(),
)))
}
}
pub fn find_constructor<'jvm>(
jvm: &mut Jvm<'jvm>,
class: impl AsRef<java::lang::Class>,
jni_descriptor: &CStr,
) -> LocalResult<'jvm, MethodPtr> {
const METHOD_NAME: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"<init>\0") };
find_method(jvm, class, METHOD_NAME, jni_descriptor, false)
}