1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
use jni::objects::{JObject, JValue};
use jni::{sys, JNIEnv, JavaVM, NativeMethod};

use super::Reference;

pub trait Object {
    fn from_reference(reference: Reference) -> Self;
    fn as_reference(&self) -> &Reference;
}

pub struct VM(JavaVM);

impl VM {
    pub fn env(&self) -> Env {
        Env::from(self.0.get_env().unwrap())
    }

    pub(crate) fn internal_clone(&self) -> VM {
        unsafe { VM(JavaVM::from_raw(self.0.get_java_vm_pointer()).unwrap()) }
    }
}

#[derive(Clone)]
pub struct Env<'a> {
    env: JNIEnv<'a>,
}

impl<'a> Env<'a> {
    pub unsafe fn new(env: *mut sys::JNIEnv) -> Env<'a> {
        Env {
            env: JNIEnv::from_raw(env).unwrap(),
        }
    }

    pub unsafe fn retain(&self, object: JObject<'a>) -> Reference {
        Reference {
            global_ref: self.unwrap(self.env.new_global_ref(object)),
            vm: VM(self.env.get_java_vm().unwrap()),
        }
    }

    pub unsafe fn prolong_lifetime<'b>(&self) -> Env<'b> {
        Env {
            env: std::mem::transmute(self.env.clone()),
        }
    }

    pub unsafe fn call_constructor(
        &self,
        name: &str,
        sig: &str,
        args: &[JValue<'a>],
    ) -> JObject<'a> {
        let args = args.into_iter().map(|&arg| arg.into()).collect::<Vec<_>>();
        let class = self.unwrap(self.env.find_class(name));
        self.unwrap(self.env.new_object(class, &sig, &args))
    }

    pub unsafe fn call_method(
        &self,
        object: JObject<'a>,
        name: &str,
        sig: &str,
        args: &[JValue],
    ) -> JValue<'a> {
        let args = args.into_iter().map(|&arg| arg.into()).collect::<Vec<_>>();
        self.unwrap(self.env.call_method(object, name, sig, &args))
    }

    pub unsafe fn register_natives(
        &self,
        name: &str,
        methods: impl IntoIterator<Item = NativeMethod>,
    ) {
        let class = self.unwrap(self.env.find_class(name));
        self.unwrap(
            self.env.register_native_methods(
                class,
                &methods
                    .into_iter()
                    .map(|method| jni::NativeMethod {
                        name: method.name.into(),
                        sig: method.sig.into(),
                        fn_ptr: method.fn_ptr,
                    })
                    .collect::<Vec<_>>(),
            ),
        );
    }

    unsafe fn unwrap<T>(&self, value: jni::errors::Result<T>) -> T {
        if value.is_err() {
            let _ = self.env.exception_describe();
        }

        value.unwrap()
    }
}

impl<'a> From<JNIEnv<'a>> for Env<'a> {
    fn from(env: JNIEnv<'a>) -> Self {
        Env { env }
    }
}