1use crate::logger::debug;
16use crate::{cache, errors, jni_utils, InvocationArg, Jvm};
17use jni_sys::jobject;
18use serde::de::DeserializeOwned;
19use serde::Serialize;
20use std::any::Any;
21use std::convert::TryFrom;
22use std::sync::mpsc::{Receiver, Sender};
23
24#[derive(Serialize)]
26pub struct Instance {
27 pub(crate) class_name: String,
29 #[serde(skip)]
33 pub(crate) jinstance: jobject,
34 #[serde(skip)]
35 pub(crate) skip_deleting_jobject: bool,
36}
37
38impl Instance {
39 pub(crate) fn new(obj: jobject, classname: &str) -> errors::Result<Instance> {
42 Ok(Instance {
43 jinstance: obj,
44 class_name: classname.to_string(),
45 skip_deleting_jobject: false,
46 })
47 }
48
49 pub fn class_name(&self) -> &str {
51 self.class_name.as_ref()
52 }
53
54 pub fn java_object(mut self) -> jobject {
56 self.skip_deleting_jobject = true;
57 self.jinstance
58 }
59
60 #[deprecated(
61 since = "0.12.0",
62 note = "Please use Instance::from_jobject or Instance::from_jobject_with_global_ref instead"
63 )]
64 pub fn from(obj: jobject) -> errors::Result<Instance> {
65 let _jvm = cache::get_thread_local_env().map_err(|_| Jvm::attach_thread());
66
67 let global =
68 jni_utils::create_global_ref_from_local_ref(obj, cache::get_thread_local_env()?)?;
69 Ok(Instance {
70 jinstance: global,
71 class_name: cache::UNKNOWN_FOR_RUST.to_string(),
72 skip_deleting_jobject: false,
73 })
74 }
75
76 pub fn from_jobject(obj: jobject) -> errors::Result<Instance> {
77 let _jvm = cache::get_thread_local_env().map_err(|_| Jvm::attach_thread());
78
79 Ok(Instance {
80 jinstance: obj,
81 class_name: cache::UNKNOWN_FOR_RUST.to_string(),
82 skip_deleting_jobject: false,
83 })
84 }
85
86 pub fn from_jobject_with_global_ref(obj: jobject) -> errors::Result<Instance> {
87 let _jvm = cache::get_thread_local_env().map_err(|_| Jvm::attach_thread());
88
89 let global =
90 jni_utils::create_global_ref_from_local_ref(obj, cache::get_thread_local_env()?)?;
91 Ok(Instance {
92 jinstance: global,
93 class_name: cache::UNKNOWN_FOR_RUST.to_string(),
94 skip_deleting_jobject: false,
95 })
96 }
97
98 fn _weak_ref(&self) -> errors::Result<Instance> {
100 Ok(Instance {
101 class_name: self.class_name.clone(),
102 jinstance: jni_utils::_create_weak_global_ref_from_global_ref(
103 self.jinstance.clone(),
104 cache::get_thread_local_env()?,
105 )?,
106 skip_deleting_jobject: false,
107 })
108 }
109}
110
111impl TryFrom<InvocationArg> for Instance {
112 type Error = errors::J4RsError;
113 fn try_from(invocation_arg: InvocationArg) -> errors::Result<Instance> {
114 let obj = invocation_arg.as_java_ptr_with_local_ref(cache::get_thread_local_env()?)?;
115 Instance::new(obj, invocation_arg.class_name())
116 }
117}
118
119impl Drop for Instance {
120 fn drop(&mut self) {
121 debug(&format!("Dropping an instance of {}", self.class_name));
122 if !self.skip_deleting_jobject {
123 if let Some(j_env) = cache::get_thread_local_env_opt() {
124 jni_utils::delete_java_ref(j_env, self.jinstance);
125 }
126 }
127 }
128}
129
130unsafe impl Send for Instance {}
131
132pub struct InstanceReceiver {
140 pub(crate) rx: Box<Receiver<Instance>>,
141 tx_address: u64,
142}
143
144impl InstanceReceiver {
145 pub(crate) fn new(rx: Receiver<Instance>, tx_address: u64) -> InstanceReceiver {
146 InstanceReceiver {
147 rx: Box::new(rx),
148 tx_address,
149 }
150 }
151
152 pub fn rx(&self) -> &Receiver<Instance> {
153 &self.rx
154 }
155}
156
157impl Drop for InstanceReceiver {
158 fn drop(&mut self) {
159 if self.tx_address > 0 {
160 debug("Dropping an InstanceReceiver");
161 let p = self.tx_address as *mut Sender<Instance>;
162 unsafe {
163 let tx = Box::from_raw(p);
164 drop(tx);
165 }
166 }
167 }
168}
169
170pub struct ChainableInstance<'a> {
172 instance: Instance,
173 jvm: &'a Jvm,
174}
175
176impl<'a> ChainableInstance<'a> {
177 pub(crate) fn new(instance: Instance, jvm: &'a Jvm) -> ChainableInstance {
178 ChainableInstance { instance, jvm }
179 }
180
181 pub(crate) fn new_with_instance_ref(
182 instance: &Instance,
183 jvm: &'a Jvm,
184 ) -> errors::Result<ChainableInstance<'a>> {
185 let cloned = jvm.clone_instance(&instance)?;
186 Ok(ChainableInstance {
187 instance: cloned,
188 jvm,
189 })
190 }
191
192 pub fn collect(self) -> Instance {
193 self.instance
194 }
195
196 pub fn invoke(
198 &self,
199 method_name: &str,
200 inv_args: &[InvocationArg],
201 ) -> errors::Result<ChainableInstance> {
202 let instance = self.jvm.invoke(&self.instance, method_name, inv_args)?;
203 Ok(ChainableInstance::new(instance, self.jvm))
204 }
205
206 pub fn clone_instance(&self) -> errors::Result<ChainableInstance> {
208 let instance = self.jvm.clone_instance(&self.instance)?;
209 Ok(ChainableInstance::new(instance, self.jvm))
210 }
211
212 pub fn cast(&self, to_class: &str) -> errors::Result<ChainableInstance> {
214 let instance = self.jvm.cast(&self.instance, to_class)?;
215 Ok(ChainableInstance::new(instance, self.jvm))
216 }
217
218 pub fn field(&self, field_name: &str) -> errors::Result<ChainableInstance> {
220 let instance = self.jvm.field(&self.instance, field_name)?;
221 Ok(ChainableInstance::new(instance, self.jvm))
222 }
223
224 pub fn to_rust<T: Any>(self) -> errors::Result<T>
226 where
227 T: DeserializeOwned,
228 {
229 self.jvm.to_rust(self.instance)
230 }
231
232 pub fn to_rust_boxed<T: Any>(self) -> errors::Result<Box<T>>
234 where
235 T: DeserializeOwned,
236 {
237 self.jvm.to_rust_boxed(self.instance)
238 }
239}