|
1 | 1 | mod fs_monitor; |
2 | 2 |
|
3 | 3 | use jni::{Executor, JNIEnv}; |
4 | | - |
5 | 4 | use jni::objects::{GlobalRef, JClass, JMethodID, JObject, JString, JValue}; |
6 | | - |
7 | | -use jni::sys::{jboolean, jlong, jint, jvalue, JNI_FALSE}; |
| 5 | +use jni::sys::{jint, jlong}; |
8 | 6 |
|
9 | 7 | use crate::fs_monitor::{Kind, NativeEventStream}; |
10 | 8 |
|
11 | | -struct Runnable2 { |
12 | | - obj: GlobalRef, |
13 | | - class: GlobalRef, // just making sure we don't lose reference to this Runnable class |
| 9 | +#[allow(dead_code)] |
| 10 | +struct HandlerExecutor { |
14 | 11 | executor: Executor, |
15 | | - root_path: String |
| 12 | + obj: GlobalRef, |
| 13 | + method: JMethodID, |
| 14 | + path: String, |
| 15 | + class: GlobalRef, // Ensure the reference to the class (of `obj`) isn't lost |
16 | 16 | } |
17 | 17 |
|
18 | | -impl Runnable2 { |
19 | | - pub fn new<'local>(env: &mut JNIEnv<'local>, root_path: String, local_recv: JObject<'local>) -> Result<Self, jni::errors::Error> { |
20 | | - let recv = env.new_global_ref(local_recv)?; |
21 | | - let class = env.new_global_ref(env.get_object_class(&recv)?)?; |
| 18 | +impl HandlerExecutor { |
| 19 | + pub fn new<'local>(env: &mut JNIEnv<'local>, path: String, obj: JObject<'local>) -> Result<Self, jni::errors::Error> { |
22 | 20 | let executor = Executor::new(Into::into(env.get_java_vm()?)); |
| 21 | + let obj = env.new_global_ref(obj)?; |
| 22 | + let class = env.new_global_ref(env.get_object_class(&obj)?)?; |
| 23 | + let method = env.get_method_id( |
| 24 | + &class, "handle", "(Ljava/lang/String;Ljava/lang/String;I)V")?; |
23 | 25 |
|
24 | | - Ok(Self { |
25 | | - obj: recv, |
26 | | - class, |
27 | | - executor, |
28 | | - root_path |
29 | | - }) |
| 26 | + Ok(Self { executor, obj, method, path, class }) |
30 | 27 | } |
31 | 28 |
|
32 | | - pub fn run2<'local>(&self, path: &String, kind: Kind) { |
| 29 | + pub fn execute<'local>(&self, path: &String, kind: Kind) { |
33 | 30 | self.executor.with_attached(|env: &mut JNIEnv<'_>| -> Result<(), jni::errors::Error> { |
34 | | - // let message = env.new_string(&path).unwrap(); |
35 | | - // eprintln!("Message: {:?}", &message.as_raw()); |
36 | | - // let class = env.find_class("java/nio/file/StandardWatchEventKinds").unwrap(); |
37 | | - // eprintln!("Class: {:?}", &class); |
38 | | - // let field = env.get_static_field(class, "ENTRY_CREATE", "Ljava/nio/file/WatchEvent$Kind;").unwrap(); |
39 | | - // eprintln!("Field: {:?}", &field); |
40 | | - |
41 | | - |
42 | | - env.call_method( |
43 | | - self.obj.as_obj(), |
44 | | - "handle", |
45 | | - "(Ljava/lang/String;Ljava/lang/String;I)V", |
46 | | - &[ |
47 | | - JValue::Object(&env.new_string(&self.root_path).unwrap()), |
48 | | - JValue::Object(&env.new_string(&path).unwrap()), |
49 | | - JValue::Int(kind as jint)]); |
50 | | - |
51 | | - // "(Ljava/lang/String;Ljava/nio/file/WatchEvent$Kind;)V", |
52 | | - // &[JValue::Object(&message), field.borrow()]); |
53 | | - |
| 31 | + unsafe { |
| 32 | + env.call_method_unchecked( |
| 33 | + self.obj.as_obj(), |
| 34 | + self.method, |
| 35 | + jni::signature::ReturnType::Primitive(jni::signature::Primitive::Void), |
| 36 | + &[ |
| 37 | + JValue::from(&env.new_string(&self.path).unwrap()).as_jni(), |
| 38 | + JValue::from(&env.new_string(&path).unwrap()).as_jni(), |
| 39 | + JValue::from(kind as jint).as_jni()] |
| 40 | + )?; |
| 41 | + } |
54 | 42 | Ok(()) |
55 | | - }); |
| 43 | + }).unwrap(); |
56 | 44 | } |
57 | 45 | } |
58 | 46 |
|
59 | | - |
60 | 47 | #[unsafe(no_mangle)] |
61 | 48 | #[allow(unused_variables)] |
62 | 49 | pub extern "system" fn Java_engineering_swat_watch_impl_mac_jni_FileSystemEvents_start<'local>( |
63 | 50 | mut env: JNIEnv<'local>, |
64 | 51 | class: JClass<'local>, |
65 | 52 | path: JString<'local>, |
66 | | - test: JObject<'local> |
67 | | -) -> jlong { |
68 | | - |
69 | | - let asdf: String = env.get_string(&path).expect("Should not fail to get string").into(); |
70 | | - |
71 | | - let g = Runnable2::new(&mut env, asdf.clone(), test).unwrap(); |
72 | | - // let h = move |path: String, flags: u32| g.run2(path, flags); |
73 | | - let h = move |path: &String, kind: Kind| g.run2(path, kind); |
74 | | - |
75 | | - let mut mon = NativeEventStream::new( |
76 | | - asdf, |
77 | | - h |
78 | | - ); |
79 | | - |
| 53 | + handler: JObject<'local>, |
| 54 | +) -> jlong |
| 55 | +{ |
| 56 | + let path: String = env.get_string(&path).expect("Should not fail to get string").into(); |
| 57 | + let handler_executor = HandlerExecutor::new(&mut env, path.clone(), handler).unwrap(); |
| 58 | + let handler = move |path: &String, kind: Kind| handler_executor.execute(path, kind); |
| 59 | + let mut mon = NativeEventStream::new(path, handler); |
80 | 60 | mon.start(); |
81 | 61 | Box::into_raw(Box::new(mon)) as jlong |
82 | 62 | } |
83 | 63 |
|
84 | 64 | #[unsafe(no_mangle)] |
85 | 65 | #[allow(unused_variables)] |
86 | 66 | pub extern "system" fn Java_engineering_swat_watch_impl_mac_jni_FileSystemEvents_stop<'local>( |
87 | | - mut env: JNIEnv<'local>, |
| 67 | + env: JNIEnv<'local>, |
88 | 68 | class: JClass<'local>, |
89 | 69 | stream: jlong, |
90 | | -) { |
| 70 | +) |
| 71 | +{ |
91 | 72 | let mon_ptr = stream as *mut NativeEventStream; |
92 | 73 | let mon = unsafe { Box::from_raw(mon_ptr) }; |
93 | 74 | mon.stop(); |
94 | | - // after this the mon will be released, as we took it back into the box |
| 75 | + // After this, the mon will be released, as it has been taken out of the box |
95 | 76 | } |
0 commit comments