Skip to main content

ri/java/classes/
hooks.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//!     http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18//! # Hooks Module JNI Bindings
19//!
20//! JNI bindings for Ri hooks classes.
21
22use jni::JNIEnv;
23use jni::objects::{JClass, JString};
24use jni::sys::{jlong, jint, jstring};
25use crate::hooks::{RiHookBus, RiHookEvent, RiHookKind, RiModulePhase};
26use crate::java::exception::check_not_null;
27
28// =============================================================================
29// RiHookBus JNI Bindings
30// =============================================================================
31
32#[no_mangle]
33pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookBus_new0(
34    _env: JNIEnv,
35    _class: JClass,
36) -> jlong {
37    let bus = Box::new(RiHookBus::new());
38    Box::into_raw(bus) as jlong
39}
40
41#[no_mangle]
42pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookBus_free0(
43    _env: JNIEnv,
44    _class: JClass,
45    ptr: jlong,
46) {
47    if ptr != 0 {
48        unsafe {
49            let _ = Box::from_raw(ptr as *mut RiHookBus);
50        }
51    }
52}
53
54#[no_mangle]
55pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookBus_emit0(
56    mut env: JNIEnv,
57    _class: JClass,
58    ptr: jlong,
59    kind_ordinal: jint,
60    module: JString,
61    phase_ordinal: jint,
62) {
63    if !check_not_null(&mut env, ptr, "RiHookBus") {
64        return;
65    }
66    
67    let bus = unsafe { &*(ptr as *const RiHookBus) };
68    
69    let kind = match kind_ordinal {
70        0 => RiHookKind::Startup,
71        1 => RiHookKind::Shutdown,
72        2 => RiHookKind::BeforeModulesInit,
73        3 => RiHookKind::AfterModulesInit,
74        4 => RiHookKind::BeforeModulesStart,
75        5 => RiHookKind::AfterModulesStart,
76        6 => RiHookKind::BeforeModulesShutdown,
77        7 => RiHookKind::AfterModulesShutdown,
78        8 => RiHookKind::ConfigReload,
79        _ => RiHookKind::Startup,
80    };
81    
82    let module_str: Option<&str> = if module.is_null() {
83        None
84    } else {
85        match env.get_string(&module) {
86            Ok(s) => Some(&s.into()),
87            Err(_) => None,
88        }
89    };
90    
91    let phase = if phase_ordinal < 0 {
92        None
93    } else {
94        Some(match phase_ordinal {
95            0 => RiModulePhase::Init,
96            1 => RiModulePhase::BeforeStart,
97            2 => RiModulePhase::Start,
98            3 => RiModulePhase::AfterStart,
99            4 => RiModulePhase::BeforeShutdown,
100            5 => RiModulePhase::Shutdown,
101            6 => RiModulePhase::AfterShutdown,
102            7 => RiModulePhase::AsyncInit,
103            8 => RiModulePhase::AsyncBeforeStart,
104            9 => RiModulePhase::AsyncStart,
105            10 => RiModulePhase::AsyncAfterStart,
106            11 => RiModulePhase::AsyncBeforeShutdown,
107            12 => RiModulePhase::AsyncShutdown,
108            13 => RiModulePhase::AsyncAfterShutdown,
109            _ => RiModulePhase::Init,
110        })
111    };
112    
113    let _ = bus.emit_simple(&kind, module_str, phase);
114}
115
116#[no_mangle]
117pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookBus_hasHandlers0(
118    mut env: JNIEnv,
119    _class: JClass,
120    ptr: jlong,
121    kind_ordinal: jint,
122) -> jni::sys::jboolean {
123    if !check_not_null(&mut env, ptr, "RiHookBus") {
124        return 0;
125    }
126    
127    let bus = unsafe { &*(ptr as *const RiHookBus) };
128    
129    let kind = match kind_ordinal {
130        0 => RiHookKind::Startup,
131        1 => RiHookKind::Shutdown,
132        2 => RiHookKind::BeforeModulesInit,
133        3 => RiHookKind::AfterModulesInit,
134        4 => RiHookKind::BeforeModulesStart,
135        5 => RiHookKind::AfterModulesStart,
136        6 => RiHookKind::BeforeModulesShutdown,
137        7 => RiHookKind::AfterModulesShutdown,
138        8 => RiHookKind::ConfigReload,
139        _ => RiHookKind::Startup,
140    };
141    
142    if bus.has_handlers(&kind) { 1 } else { 0 }
143}
144
145// =============================================================================
146// RiHookEvent JNI Bindings
147// =============================================================================
148
149#[no_mangle]
150pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookEvent_new0(
151    mut env: JNIEnv,
152    _class: JClass,
153    kind_ordinal: jint,
154    module: JString,
155    phase_ordinal: jint,
156) -> jlong {
157    let kind = match kind_ordinal {
158        0 => RiHookKind::Startup,
159        1 => RiHookKind::Shutdown,
160        2 => RiHookKind::BeforeModulesInit,
161        3 => RiHookKind::AfterModulesInit,
162        4 => RiHookKind::BeforeModulesStart,
163        5 => RiHookKind::AfterModulesStart,
164        6 => RiHookKind::BeforeModulesShutdown,
165        7 => RiHookKind::AfterModulesShutdown,
166        8 => RiHookKind::ConfigReload,
167        _ => RiHookKind::Startup,
168    };
169    
170    let module_str: Option<String> = if module.is_null() {
171        None
172    } else {
173        Some(env.get_string(&module)
174            .expect("Failed to get module")
175            .into())
176    };
177    
178    let phase = if phase_ordinal < 0 {
179        None
180    } else {
181        Some(match phase_ordinal {
182            0 => RiModulePhase::Init,
183            1 => RiModulePhase::BeforeStart,
184            2 => RiModulePhase::Start,
185            3 => RiModulePhase::AfterStart,
186            4 => RiModulePhase::BeforeShutdown,
187            5 => RiModulePhase::Shutdown,
188            6 => RiModulePhase::AfterShutdown,
189            7 => RiModulePhase::AsyncInit,
190            8 => RiModulePhase::AsyncBeforeStart,
191            9 => RiModulePhase::AsyncStart,
192            10 => RiModulePhase::AsyncAfterStart,
193            11 => RiModulePhase::AsyncBeforeShutdown,
194            12 => RiModulePhase::AsyncShutdown,
195            13 => RiModulePhase::AsyncAfterShutdown,
196            _ => RiModulePhase::Init,
197        })
198    };
199    
200    let event = Box::new(RiHookEvent::new(kind, module_str, phase));
201    Box::into_raw(event) as jlong
202}
203
204#[no_mangle]
205pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookEvent_getKind0(
206    mut env: JNIEnv,
207    _class: JClass,
208    ptr: jlong,
209) -> jint {
210    if !check_not_null(&mut env, ptr, "RiHookEvent") {
211        return 0;
212    }
213    
214    let event = unsafe { &*(ptr as *const RiHookEvent) };
215    match event.kind {
216        RiHookKind::Startup => 0,
217        RiHookKind::Shutdown => 1,
218        RiHookKind::BeforeModulesInit => 2,
219        RiHookKind::AfterModulesInit => 3,
220        RiHookKind::BeforeModulesStart => 4,
221        RiHookKind::AfterModulesStart => 5,
222        RiHookKind::BeforeModulesShutdown => 6,
223        RiHookKind::AfterModulesShutdown => 7,
224        RiHookKind::ConfigReload => 8,
225    }
226}
227
228#[no_mangle]
229pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookEvent_getModule0(
230    mut env: JNIEnv,
231    _class: JClass,
232    ptr: jlong,
233) -> jstring {
234    if !check_not_null(&mut env, ptr, "RiHookEvent") {
235        return std::ptr::null_mut();
236    }
237    
238    let event = unsafe { &*(ptr as *const RiHookEvent) };
239    match &event.module {
240        Some(module) => env.new_string(module)
241            .expect("Failed to create module string")
242            .into_raw(),
243        None => std::ptr::null_mut(),
244    }
245}
246
247#[no_mangle]
248pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookEvent_getPhase0(
249    mut env: JNIEnv,
250    _class: JClass,
251    ptr: jlong,
252) -> jint {
253    if !check_not_null(&mut env, ptr, "RiHookEvent") {
254        return -1;
255    }
256    
257    let event = unsafe { &*(ptr as *const RiHookEvent) };
258    match &event.phase {
259        Some(phase) => match phase {
260            RiModulePhase::Init => 0,
261            RiModulePhase::BeforeStart => 1,
262            RiModulePhase::Start => 2,
263            RiModulePhase::AfterStart => 3,
264            RiModulePhase::BeforeShutdown => 4,
265            RiModulePhase::Shutdown => 5,
266            RiModulePhase::AfterShutdown => 6,
267            RiModulePhase::AsyncInit => 7,
268            RiModulePhase::AsyncBeforeStart => 8,
269            RiModulePhase::AsyncStart => 9,
270            RiModulePhase::AsyncAfterStart => 10,
271            RiModulePhase::AsyncBeforeShutdown => 11,
272            RiModulePhase::AsyncShutdown => 12,
273            RiModulePhase::AsyncAfterShutdown => 13,
274        },
275        None => -1,
276    }
277}
278
279#[no_mangle]
280pub extern "system" fn Java_com_dunimd_ri_hooks_RiHookEvent_free0(
281    _env: JNIEnv,
282    _class: JClass,
283    ptr: jlong,
284) {
285    if ptr != 0 {
286        unsafe {
287            let _ = Box::from_raw(ptr as *mut RiHookEvent);
288        }
289    }
290}