Skip to main content

ri/java/classes/
gateway.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//! # Gateway Module JNI Bindings
19//!
20//! JNI bindings for Ri gateway classes.
21
22use crate::core::RiResult;
23use crate::gateway::{
24    RiBackendServer, RiCircuitBreaker, RiCircuitBreakerConfig, RiCircuitBreakerMetrics,
25    RiCircuitBreakerState, RiGateway, RiGatewayConfig, RiGatewayResponse, RiLoadBalancer,
26    RiLoadBalancerServerStats, RiLoadBalancerStrategy, RiRateLimitConfig, RiRateLimitStats,
27    RiRateLimiter, RiRoute, RiRouter, RiSlidingWindowRateLimiter,
28};
29use jni::objects::{JClass, JString};
30use jni::sys::{jboolean, jdouble, jint, jlong, jstring};
31use jni::JNIEnv;
32use std::future::Future;
33use std::pin::Pin;
34
35// ============================================================================
36// RiGateway
37// ============================================================================
38
39#[no_mangle]
40pub extern "system" fn Java_com_dunimd_ri_gateway_RiGateway_new0(
41    _env: JNIEnv,
42    _class: JClass,
43) -> jlong {
44    let gateway = Box::new(RiGateway::new());
45    Box::into_raw(gateway) as jlong
46}
47
48#[no_mangle]
49pub extern "system" fn Java_com_dunimd_ri_gateway_RiGateway_free0(
50    _env: JNIEnv,
51    _class: JClass,
52    ptr: jlong,
53) {
54    if ptr != 0 {
55        unsafe {
56            let _ = Box::from_raw(ptr as *mut RiGateway);
57        }
58    }
59}
60
61// ============================================================================
62// RiGatewayConfig
63// ============================================================================
64
65#[no_mangle]
66pub extern "system" fn Java_com_dunimd_ri_gateway_RiGatewayConfig_new0(
67    _env: JNIEnv,
68    _class: JClass,
69) -> jlong {
70    let config = Box::new(RiGatewayConfig::default());
71    Box::into_raw(config) as jlong
72}
73
74#[no_mangle]
75pub extern "system" fn Java_com_dunimd_ri_gateway_RiGatewayConfig_free0(
76    _env: JNIEnv,
77    _class: JClass,
78    ptr: jlong,
79) {
80    if ptr != 0 {
81        unsafe {
82            let _ = Box::from_raw(ptr as *mut RiGatewayConfig);
83        }
84    }
85}
86
87// ============================================================================
88// RiRouter
89// ============================================================================
90
91#[no_mangle]
92pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_new0(
93    _env: JNIEnv,
94    _class: JClass,
95) -> jlong {
96    let router = Box::new(RiRouter::new());
97    Box::into_raw(router) as jlong
98}
99
100#[no_mangle]
101pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_free0(
102    _env: JNIEnv,
103    _class: JClass,
104    ptr: jlong,
105) {
106    if ptr != 0 {
107        unsafe {
108            let _ = Box::from_raw(ptr as *mut RiRouter);
109        }
110    }
111}
112
113#[no_mangle]
114pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addRoute0(
115    _env: JNIEnv,
116    _class: JClass,
117    ptr: jlong,
118    route_ptr: jlong,
119) {
120    if ptr != 0 && route_ptr != 0 {
121        unsafe {
122            let router = &*(ptr as *const RiRouter);
123            // Clone the route: the Java-side RiRoute wrapper keeps ownership of its
124            // own native pointer and may free it via close(), so we must not consume it.
125            let route = &*(route_ptr as *const RiRoute);
126            router.add_route(route.clone());
127        }
128    }
129}
130
131#[no_mangle]
132pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addGetRoute0(
133    mut env: JNIEnv,
134    _class: JClass,
135    ptr: jlong,
136    path: JString,
137) {
138    if ptr != 0 {
139        let path_str: String = match env.get_string(&path) {
140            Ok(s) => s.into(),
141            Err(_) => {
142                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
143                return;
144            }
145        };
146        unsafe {
147            let router = &*(ptr as *const RiRouter);
148            let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(
149                |_req| {
150                    Box::pin(async move {
151                        Ok(crate::gateway::RiGatewayResponse::new(
152                            200,
153                            b"OK".to_vec(),
154                            String::new(),
155                        ))
156                    }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
157                },
158            );
159            router.get(&path_str, handler);
160        }
161    }
162}
163
164#[no_mangle]
165pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addPostRoute0(
166    mut env: JNIEnv,
167    _class: JClass,
168    ptr: jlong,
169    path: JString,
170) {
171    if ptr != 0 {
172        let path_str: String = match env.get_string(&path) {
173            Ok(s) => s.into(),
174            Err(_) => {
175                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
176                return;
177            }
178        };
179        unsafe {
180            let router = &*(ptr as *const RiRouter);
181            let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(
182                |_req| {
183                    Box::pin(async move {
184                        Ok(crate::gateway::RiGatewayResponse::new(
185                            200,
186                            b"OK".to_vec(),
187                            String::new(),
188                        ))
189                    }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
190                },
191            );
192            router.post(&path_str, handler);
193        }
194    }
195}
196
197#[no_mangle]
198pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addPutRoute0(
199    mut env: JNIEnv,
200    _class: JClass,
201    ptr: jlong,
202    path: JString,
203) {
204    if ptr != 0 {
205        let path_str: String = match env.get_string(&path) {
206            Ok(s) => s.into(),
207            Err(_) => {
208                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
209                return;
210            }
211        };
212        unsafe {
213            let router = &*(ptr as *const RiRouter);
214            let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(
215                |_req| {
216                    Box::pin(async move {
217                        Ok(crate::gateway::RiGatewayResponse::new(
218                            200,
219                            b"OK".to_vec(),
220                            String::new(),
221                        ))
222                    }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
223                },
224            );
225            router.put(&path_str, handler);
226        }
227    }
228}
229
230#[no_mangle]
231pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addDeleteRoute0(
232    mut env: JNIEnv,
233    _class: JClass,
234    ptr: jlong,
235    path: JString,
236) {
237    if ptr != 0 {
238        let path_str: String = match env.get_string(&path) {
239            Ok(s) => s.into(),
240            Err(_) => {
241                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
242                return;
243            }
244        };
245        unsafe {
246            let router = &*(ptr as *const RiRouter);
247            let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(
248                |_req| {
249                    Box::pin(async move {
250                        Ok(crate::gateway::RiGatewayResponse::new(
251                            200,
252                            b"OK".to_vec(),
253                            String::new(),
254                        ))
255                    }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
256                },
257            );
258            router.delete(&path_str, handler);
259        }
260    }
261}
262
263#[no_mangle]
264pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addPatchRoute0(
265    mut env: JNIEnv,
266    _class: JClass,
267    ptr: jlong,
268    path: JString,
269) {
270    if ptr != 0 {
271        let path_str: String = match env.get_string(&path) {
272            Ok(s) => s.into(),
273            Err(_) => {
274                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
275                return;
276            }
277        };
278        unsafe {
279            let router = &*(ptr as *const RiRouter);
280            let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(
281                |_req| {
282                    Box::pin(async move {
283                        Ok(crate::gateway::RiGatewayResponse::new(
284                            200,
285                            b"OK".to_vec(),
286                            String::new(),
287                        ))
288                    }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
289                },
290            );
291            router.patch(&path_str, handler);
292        }
293    }
294}
295
296#[no_mangle]
297pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addOptionsRoute0(
298    mut env: JNIEnv,
299    _class: JClass,
300    ptr: jlong,
301    path: JString,
302) {
303    if ptr != 0 {
304        let path_str: String = match env.get_string(&path) {
305            Ok(s) => s.into(),
306            Err(_) => {
307                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
308                return;
309            }
310        };
311        unsafe {
312            let router = &*(ptr as *const RiRouter);
313            let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(
314                |_req| {
315                    Box::pin(async move {
316                        Ok(crate::gateway::RiGatewayResponse::new(
317                            200,
318                            b"OK".to_vec(),
319                            String::new(),
320                        ))
321                    }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
322                },
323            );
324            router.options(&path_str, handler);
325        }
326    }
327}
328
329#[no_mangle]
330pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_addCustomRoute0(
331    mut env: JNIEnv,
332    _class: JClass,
333    ptr: jlong,
334    method: JString,
335    path: JString,
336) {
337    if ptr != 0 {
338        let method_str: String = match env.get_string(&method) {
339            Ok(s) => s.into(),
340            Err(_) => {
341                crate::java::exception::throw_ri_error(&mut env, "Invalid method string");
342                return;
343            }
344        };
345        let path_str: String = match env.get_string(&path) {
346            Ok(s) => s.into(),
347            Err(_) => {
348                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
349                return;
350            }
351        };
352        unsafe {
353            let router = &*(ptr as *const RiRouter);
354            let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(
355                |_req| {
356                    Box::pin(async move {
357                        Ok(crate::gateway::RiGatewayResponse::new(
358                            200,
359                            b"OK".to_vec(),
360                            String::new(),
361                        ))
362                    }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
363                },
364            );
365            let route = RiRoute::new(method_str, path_str, handler);
366            router.add_route(route);
367        }
368    }
369}
370
371#[no_mangle]
372pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_getRouteCount0(
373    _env: JNIEnv,
374    _class: JClass,
375    ptr: jlong,
376) -> jint {
377    if ptr != 0 {
378        unsafe {
379            let router = &*(ptr as *const RiRouter);
380            router.route_count() as jint
381        }
382    } else {
383        0
384    }
385}
386
387#[no_mangle]
388pub extern "system" fn Java_com_dunimd_ri_gateway_RiRouter_clearRoutes0(
389    _env: JNIEnv,
390    _class: JClass,
391    ptr: jlong,
392) {
393    if ptr != 0 {
394        unsafe {
395            let router = &*(ptr as *const RiRouter);
396            router.clear_routes();
397        }
398    }
399}
400
401// ============================================================================
402// RiRoute
403// ============================================================================
404
405#[no_mangle]
406pub extern "system" fn Java_com_dunimd_ri_gateway_RiRoute_new0(
407    mut env: JNIEnv,
408    _class: JClass,
409    method: JString,
410    path: JString,
411) -> jlong {
412    let method_str: String = match env.get_string(&method) {
413        Ok(s) => s.into(),
414        Err(_) => {
415            crate::java::exception::throw_ri_error(&mut env, "Invalid method string");
416            return 0;
417        }
418    };
419    let path_str: String = match env.get_string(&path) {
420        Ok(s) => s.into(),
421        Err(_) => {
422            crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
423            return 0;
424        }
425    };
426
427    let handler: crate::gateway::RiRouteHandler = std::sync::Arc::new(|_req| {
428        Box::pin(async move {
429            Ok(crate::gateway::RiGatewayResponse::new(
430                200,
431                b"OK".to_vec(),
432                String::new(),
433            ))
434        }) as Pin<Box<dyn Future<Output = RiResult<RiGatewayResponse>> + Send>>
435    });
436
437    let route = Box::new(RiRoute::new(method_str, path_str, handler));
438    Box::into_raw(route) as jlong
439}
440
441#[no_mangle]
442pub extern "system" fn Java_com_dunimd_ri_gateway_RiRoute_free0(
443    _env: JNIEnv,
444    _class: JClass,
445    ptr: jlong,
446) {
447    if ptr != 0 {
448        unsafe {
449            let _ = Box::from_raw(ptr as *mut RiRoute);
450        }
451    }
452}
453
454#[no_mangle]
455pub extern "system" fn Java_com_dunimd_ri_gateway_RiRoute_getMethod0(
456    env: JNIEnv,
457    _class: JClass,
458    ptr: jlong,
459) -> jstring {
460    if ptr != 0 {
461        unsafe {
462            let route = &*(ptr as *const RiRoute);
463            match env.new_string(&route.method) {
464            Ok(s) => s.into_raw(),
465            Err(_) => std::ptr::null_mut(),
466        }
467        }
468    } else {
469        std::ptr::null_mut()
470    }
471}
472
473#[no_mangle]
474pub extern "system" fn Java_com_dunimd_ri_gateway_RiRoute_getPath0(
475    env: JNIEnv,
476    _class: JClass,
477    ptr: jlong,
478) -> jstring {
479    if ptr != 0 {
480        unsafe {
481            let route = &*(ptr as *const RiRoute);
482            match env.new_string(&route.path) {
483            Ok(s) => s.into_raw(),
484            Err(_) => std::ptr::null_mut(),
485        }
486        }
487    } else {
488        std::ptr::null_mut()
489    }
490}
491
492// ============================================================================
493// RiRateLimitConfig
494// ============================================================================
495
496#[no_mangle]
497pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_new0(
498    _env: JNIEnv,
499    _class: JClass,
500) -> jlong {
501    let config = Box::new(RiRateLimitConfig::default());
502    Box::into_raw(config) as jlong
503}
504
505#[no_mangle]
506pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_newWithValues0(
507    _env: JNIEnv,
508    _class: JClass,
509    requests_per_second: jint,
510    burst_size: jint,
511    window_seconds: jlong,
512) -> jlong {
513    let config = Box::new(RiRateLimitConfig {
514        requests_per_second: requests_per_second as u32,
515        burst_size: burst_size as u32,
516        window_seconds: window_seconds as u64,
517        max_keys: 10000,
518    });
519    Box::into_raw(config) as jlong
520}
521
522#[no_mangle]
523pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_free0(
524    _env: JNIEnv,
525    _class: JClass,
526    ptr: jlong,
527) {
528    if ptr != 0 {
529        unsafe {
530            let _ = Box::from_raw(ptr as *mut RiRateLimitConfig);
531        }
532    }
533}
534
535#[no_mangle]
536pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_getRequestsPerSecond0(
537    _env: JNIEnv,
538    _class: JClass,
539    ptr: jlong,
540) -> jint {
541    if ptr != 0 {
542        unsafe {
543            let config = &*(ptr as *const RiRateLimitConfig);
544            config.requests_per_second as jint
545        }
546    } else {
547        0
548    }
549}
550
551#[no_mangle]
552pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_setRequestsPerSecond0(
553    _env: JNIEnv,
554    _class: JClass,
555    ptr: jlong,
556    value: jint,
557) {
558    if ptr != 0 {
559        unsafe {
560            let config = &mut *(ptr as *mut RiRateLimitConfig);
561            config.requests_per_second = value as u32;
562        }
563    }
564}
565
566#[no_mangle]
567pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_getBurstSize0(
568    _env: JNIEnv,
569    _class: JClass,
570    ptr: jlong,
571) -> jint {
572    if ptr != 0 {
573        unsafe {
574            let config = &*(ptr as *const RiRateLimitConfig);
575            config.burst_size as jint
576        }
577    } else {
578        0
579    }
580}
581
582#[no_mangle]
583pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_setBurstSize0(
584    _env: JNIEnv,
585    _class: JClass,
586    ptr: jlong,
587    value: jint,
588) {
589    if ptr != 0 {
590        unsafe {
591            let config = &mut *(ptr as *mut RiRateLimitConfig);
592            config.burst_size = value as u32;
593        }
594    }
595}
596
597#[no_mangle]
598pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_getWindowSeconds0(
599    _env: JNIEnv,
600    _class: JClass,
601    ptr: jlong,
602) -> jlong {
603    if ptr != 0 {
604        unsafe {
605            let config = &*(ptr as *const RiRateLimitConfig);
606            config.window_seconds as jlong
607        }
608    } else {
609        0
610    }
611}
612
613#[no_mangle]
614pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitConfig_setWindowSeconds0(
615    _env: JNIEnv,
616    _class: JClass,
617    ptr: jlong,
618    value: jlong,
619) {
620    if ptr != 0 {
621        unsafe {
622            let config = &mut *(ptr as *mut RiRateLimitConfig);
623            config.window_seconds = value as u64;
624        }
625    }
626}
627
628// ============================================================================
629// RiRateLimitStats
630// ============================================================================
631
632#[no_mangle]
633pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitStats_new0(
634    _env: JNIEnv,
635    _class: JClass,
636    current_tokens: jlong,
637    total_requests: jlong,
638) -> jlong {
639    let stats = Box::new(RiRateLimitStats {
640        current_tokens: current_tokens as usize,
641        total_requests: total_requests as usize,
642    });
643    Box::into_raw(stats) as jlong
644}
645
646#[no_mangle]
647pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitStats_free0(
648    _env: JNIEnv,
649    _class: JClass,
650    ptr: jlong,
651) {
652    if ptr != 0 {
653        unsafe {
654            let _ = Box::from_raw(ptr as *mut RiRateLimitStats);
655        }
656    }
657}
658
659#[no_mangle]
660pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitStats_getCurrentTokens0(
661    _env: JNIEnv,
662    _class: JClass,
663    ptr: jlong,
664) -> jlong {
665    if ptr != 0 {
666        unsafe {
667            let stats = &*(ptr as *const RiRateLimitStats);
668            stats.current_tokens as jlong
669        }
670    } else {
671        0
672    }
673}
674
675#[no_mangle]
676pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimitStats_getTotalRequests0(
677    _env: JNIEnv,
678    _class: JClass,
679    ptr: jlong,
680) -> jlong {
681    if ptr != 0 {
682        unsafe {
683            let stats = &*(ptr as *const RiRateLimitStats);
684            stats.total_requests as jlong
685        }
686    } else {
687        0
688    }
689}
690
691// ============================================================================
692// RiRateLimiter
693// ============================================================================
694
695#[no_mangle]
696pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_new0(
697    _env: JNIEnv,
698    _class: JClass,
699    config_ptr: jlong,
700) -> jlong {
701    let config = if config_ptr != 0 {
702        unsafe { (*(config_ptr as *const RiRateLimitConfig)).clone() }
703    } else {
704        RiRateLimitConfig::default()
705    };
706    let limiter = Box::new(RiRateLimiter::new(config));
707    Box::into_raw(limiter) as jlong
708}
709
710#[no_mangle]
711pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_free0(
712    _env: JNIEnv,
713    _class: JClass,
714    ptr: jlong,
715) {
716    if ptr != 0 {
717        unsafe {
718            let _ = Box::from_raw(ptr as *mut RiRateLimiter);
719        }
720    }
721}
722
723#[no_mangle]
724pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_checkRateLimit0(
725    mut env: JNIEnv,
726    _class: JClass,
727    ptr: jlong,
728    key: JString,
729    tokens: jint,
730) -> jboolean {
731    if ptr != 0 {
732        let key_str: String = match env.get_string(&key) {
733            Ok(s) => s.into(),
734            Err(_) => {
735                crate::java::exception::throw_ri_error(&mut env, "Invalid key string");
736                return 0;
737            }
738        };
739        unsafe {
740            let limiter = &*(ptr as *const RiRateLimiter);
741            limiter.check_rate_limit(&key_str, tokens as usize) as jboolean
742        }
743    } else {
744        0
745    }
746}
747
748#[no_mangle]
749pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_getStats0(
750    mut env: JNIEnv,
751    _class: JClass,
752    ptr: jlong,
753    key: JString,
754) -> jlong {
755    if ptr != 0 {
756        let key_str: String = match env.get_string(&key) {
757            Ok(s) => s.into(),
758            Err(_) => {
759                crate::java::exception::throw_ri_error(&mut env, "Invalid key string");
760                return 0;
761            }
762        };
763        unsafe {
764            let limiter = &*(ptr as *const RiRateLimiter);
765            if let Some(stats) = limiter.get_stats(&key_str) {
766                Box::into_raw(Box::new(stats)) as jlong
767            } else {
768                0
769            }
770        }
771    } else {
772        0
773    }
774}
775
776#[no_mangle]
777pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_getRemaining0(
778    mut env: JNIEnv,
779    _class: JClass,
780    ptr: jlong,
781    key: JString,
782) -> jdouble {
783    if ptr != 0 {
784        let key_str: String = match env.get_string(&key) {
785            Ok(s) => s.into(),
786            Err(_) => {
787                crate::java::exception::throw_ri_error(&mut env, "Invalid key string");
788                return 0.0;
789            }
790        };
791        unsafe {
792            let limiter = &*(ptr as *const RiRateLimiter);
793            limiter.get_remaining(&key_str).unwrap_or(0.0)
794        }
795    } else {
796        0.0
797    }
798}
799
800#[no_mangle]
801pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_resetBucket0(
802    mut env: JNIEnv,
803    _class: JClass,
804    ptr: jlong,
805    key: JString,
806) {
807    if ptr != 0 {
808        let key_str: String = match env.get_string(&key) {
809            Ok(s) => s.into(),
810            Err(_) => {
811                crate::java::exception::throw_ri_error(&mut env, "Invalid key string");
812                return;
813            }
814        };
815        unsafe {
816            let limiter = &*(ptr as *const RiRateLimiter);
817            limiter.reset_bucket(&key_str);
818        }
819    }
820}
821
822#[no_mangle]
823pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_clearAllBuckets0(
824    _env: JNIEnv,
825    _class: JClass,
826    ptr: jlong,
827) {
828    if ptr != 0 {
829        unsafe {
830            let limiter = &*(ptr as *const RiRateLimiter);
831            limiter.clear_all_buckets();
832        }
833    }
834}
835
836#[no_mangle]
837pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_getConfig0(
838    _env: JNIEnv,
839    _class: JClass,
840    ptr: jlong,
841) -> jlong {
842    if ptr != 0 {
843        unsafe {
844            let limiter = &*(ptr as *const RiRateLimiter);
845            let config = limiter.get_config();
846            Box::into_raw(Box::new(config)) as jlong
847        }
848    } else {
849        0
850    }
851}
852
853#[no_mangle]
854pub extern "system" fn Java_com_dunimd_ri_gateway_RiRateLimiter_bucketCount0(
855    _env: JNIEnv,
856    _class: JClass,
857    ptr: jlong,
858) -> jint {
859    if ptr != 0 {
860        unsafe {
861            let limiter = &*(ptr as *const RiRateLimiter);
862            limiter.bucket_count() as jint
863        }
864    } else {
865        0
866    }
867}
868
869// ============================================================================
870// RiSlidingWindowRateLimiter
871// ============================================================================
872
873#[no_mangle]
874pub extern "system" fn Java_com_dunimd_ri_gateway_RiSlidingWindowRateLimiter_new0(
875    _env: JNIEnv,
876    _class: JClass,
877    max_requests: jint,
878    window_seconds: jlong,
879) -> jlong {
880    let limiter = Box::new(RiSlidingWindowRateLimiter::new(
881        max_requests as u32,
882        window_seconds as u64,
883    ));
884    Box::into_raw(limiter) as jlong
885}
886
887#[no_mangle]
888pub extern "system" fn Java_com_dunimd_ri_gateway_RiSlidingWindowRateLimiter_free0(
889    _env: JNIEnv,
890    _class: JClass,
891    ptr: jlong,
892) {
893    if ptr != 0 {
894        unsafe {
895            let _ = Box::from_raw(ptr as *mut RiSlidingWindowRateLimiter);
896        }
897    }
898}
899
900#[no_mangle]
901pub extern "system" fn Java_com_dunimd_ri_gateway_RiSlidingWindowRateLimiter_allowRequest0(
902    _env: JNIEnv,
903    _class: JClass,
904    ptr: jlong,
905) -> jboolean {
906    if ptr != 0 {
907        unsafe {
908            let limiter = &*(ptr as *const RiSlidingWindowRateLimiter);
909            limiter.allow_request() as jboolean
910        }
911    } else {
912        0
913    }
914}
915
916#[no_mangle]
917pub extern "system" fn Java_com_dunimd_ri_gateway_RiSlidingWindowRateLimiter_getCurrentCount0(
918    _env: JNIEnv,
919    _class: JClass,
920    ptr: jlong,
921) -> jint {
922    if ptr != 0 {
923        unsafe {
924            let limiter = &*(ptr as *const RiSlidingWindowRateLimiter);
925            limiter.get_current_count() as jint
926        }
927    } else {
928        0
929    }
930}
931
932#[no_mangle]
933pub extern "system" fn Java_com_dunimd_ri_gateway_RiSlidingWindowRateLimiter_reset0(
934    _env: JNIEnv,
935    _class: JClass,
936    ptr: jlong,
937) {
938    if ptr != 0 {
939        unsafe {
940            let limiter = &*(ptr as *const RiSlidingWindowRateLimiter);
941            limiter.reset();
942        }
943    }
944}
945
946#[no_mangle]
947pub extern "system" fn Java_com_dunimd_ri_gateway_RiSlidingWindowRateLimiter_getMaxRequests0(
948    _env: JNIEnv,
949    _class: JClass,
950    ptr: jlong,
951) -> jint {
952    if ptr != 0 {
953        unsafe {
954            let limiter = &*(ptr as *const RiSlidingWindowRateLimiter);
955            limiter.get_max_requests() as jint
956        }
957    } else {
958        0
959    }
960}
961
962#[no_mangle]
963pub extern "system" fn Java_com_dunimd_ri_gateway_RiSlidingWindowRateLimiter_getWindowSeconds0(
964    _env: JNIEnv,
965    _class: JClass,
966    ptr: jlong,
967) -> jlong {
968    if ptr != 0 {
969        unsafe {
970            let limiter = &*(ptr as *const RiSlidingWindowRateLimiter);
971            limiter.get_window_seconds() as jlong
972        }
973    } else {
974        0
975    }
976}
977
978// ============================================================================
979// RiCircuitBreakerConfig
980// ============================================================================
981
982#[no_mangle]
983pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_new0(
984    _env: JNIEnv,
985    _class: JClass,
986) -> jlong {
987    let config = Box::new(RiCircuitBreakerConfig::default());
988    Box::into_raw(config) as jlong
989}
990
991#[no_mangle]
992pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_newWithValues0(
993    _env: JNIEnv,
994    _class: JClass,
995    failure_threshold: jint,
996    success_threshold: jint,
997    timeout_seconds: jlong,
998    monitoring_period_seconds: jlong,
999) -> jlong {
1000    let config = Box::new(RiCircuitBreakerConfig {
1001        failure_threshold: failure_threshold as u32,
1002        success_threshold: success_threshold as u32,
1003        timeout_seconds: timeout_seconds as u64,
1004        monitoring_period_seconds: monitoring_period_seconds as u64,
1005    });
1006    Box::into_raw(config) as jlong
1007}
1008
1009#[no_mangle]
1010pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_free0(
1011    _env: JNIEnv,
1012    _class: JClass,
1013    ptr: jlong,
1014) {
1015    if ptr != 0 {
1016        unsafe {
1017            let _ = Box::from_raw(ptr as *mut RiCircuitBreakerConfig);
1018        }
1019    }
1020}
1021
1022#[no_mangle]
1023pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_getFailureThreshold0(
1024    _env: JNIEnv,
1025    _class: JClass,
1026    ptr: jlong,
1027) -> jint {
1028    if ptr != 0 {
1029        unsafe {
1030            let config = &*(ptr as *const RiCircuitBreakerConfig);
1031            config.failure_threshold as jint
1032        }
1033    } else {
1034        0
1035    }
1036}
1037
1038#[no_mangle]
1039pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_setFailureThreshold0(
1040    _env: JNIEnv,
1041    _class: JClass,
1042    ptr: jlong,
1043    value: jint,
1044) {
1045    if ptr != 0 {
1046        unsafe {
1047            let config = &mut *(ptr as *mut RiCircuitBreakerConfig);
1048            config.failure_threshold = value as u32;
1049        }
1050    }
1051}
1052
1053#[no_mangle]
1054pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_getSuccessThreshold0(
1055    _env: JNIEnv,
1056    _class: JClass,
1057    ptr: jlong,
1058) -> jint {
1059    if ptr != 0 {
1060        unsafe {
1061            let config = &*(ptr as *const RiCircuitBreakerConfig);
1062            config.success_threshold as jint
1063        }
1064    } else {
1065        0
1066    }
1067}
1068
1069#[no_mangle]
1070pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_setSuccessThreshold0(
1071    _env: JNIEnv,
1072    _class: JClass,
1073    ptr: jlong,
1074    value: jint,
1075) {
1076    if ptr != 0 {
1077        unsafe {
1078            let config = &mut *(ptr as *mut RiCircuitBreakerConfig);
1079            config.success_threshold = value as u32;
1080        }
1081    }
1082}
1083
1084#[no_mangle]
1085pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_getTimeoutSeconds0(
1086    _env: JNIEnv,
1087    _class: JClass,
1088    ptr: jlong,
1089) -> jlong {
1090    if ptr != 0 {
1091        unsafe {
1092            let config = &*(ptr as *const RiCircuitBreakerConfig);
1093            config.timeout_seconds as jlong
1094        }
1095    } else {
1096        0
1097    }
1098}
1099
1100#[no_mangle]
1101pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_setTimeoutSeconds0(
1102    _env: JNIEnv,
1103    _class: JClass,
1104    ptr: jlong,
1105    value: jlong,
1106) {
1107    if ptr != 0 {
1108        unsafe {
1109            let config = &mut *(ptr as *mut RiCircuitBreakerConfig);
1110            config.timeout_seconds = value as u64;
1111        }
1112    }
1113}
1114
1115#[no_mangle]
1116pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_getMonitoringPeriodSeconds0(
1117    _env: JNIEnv,
1118    _class: JClass,
1119    ptr: jlong,
1120) -> jlong {
1121    if ptr != 0 {
1122        unsafe {
1123            let config = &*(ptr as *const RiCircuitBreakerConfig);
1124            config.monitoring_period_seconds as jlong
1125        }
1126    } else {
1127        0
1128    }
1129}
1130
1131#[no_mangle]
1132pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerConfig_setMonitoringPeriodSeconds0(
1133    _env: JNIEnv,
1134    _class: JClass,
1135    ptr: jlong,
1136    value: jlong,
1137) {
1138    if ptr != 0 {
1139        unsafe {
1140            let config = &mut *(ptr as *mut RiCircuitBreakerConfig);
1141            config.monitoring_period_seconds = value as u64;
1142        }
1143    }
1144}
1145
1146// ============================================================================
1147// RiCircuitBreakerMetrics
1148// ============================================================================
1149
1150#[no_mangle]
1151pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerMetrics_new0(
1152    mut env: JNIEnv,
1153    _class: JClass,
1154    state: JString,
1155    failure_count: jlong,
1156    success_count: jlong,
1157    consecutive_failures: jlong,
1158    consecutive_successes: jlong,
1159) -> jlong {
1160    let state_str: String = match env.get_string(&state) {
1161        Ok(s) => s.into(),
1162        Err(_) => {
1163            crate::java::exception::throw_ri_error(&mut env, "Invalid state string");
1164            return 0;
1165        }
1166    };
1167    let metrics = Box::new(RiCircuitBreakerMetrics {
1168        state: state_str,
1169        failure_count: failure_count as usize,
1170        success_count: success_count as usize,
1171        consecutive_failures: consecutive_failures as usize,
1172        consecutive_successes: consecutive_successes as usize,
1173    });
1174    Box::into_raw(metrics) as jlong
1175}
1176
1177#[no_mangle]
1178pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerMetrics_free0(
1179    _env: JNIEnv,
1180    _class: JClass,
1181    ptr: jlong,
1182) {
1183    if ptr != 0 {
1184        unsafe {
1185            let _ = Box::from_raw(ptr as *mut RiCircuitBreakerMetrics);
1186        }
1187    }
1188}
1189
1190#[no_mangle]
1191pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerMetrics_getState0(
1192    env: JNIEnv,
1193    _class: JClass,
1194    ptr: jlong,
1195) -> jstring {
1196    if ptr != 0 {
1197        unsafe {
1198            let metrics = &*(ptr as *const RiCircuitBreakerMetrics);
1199            match env.new_string(&metrics.state) {
1200            Ok(s) => s.into_raw(),
1201            Err(_) => std::ptr::null_mut(),
1202        }
1203        }
1204    } else {
1205        std::ptr::null_mut()
1206    }
1207}
1208
1209#[no_mangle]
1210pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerMetrics_getFailureCount0(
1211    _env: JNIEnv,
1212    _class: JClass,
1213    ptr: jlong,
1214) -> jlong {
1215    if ptr != 0 {
1216        unsafe {
1217            let metrics = &*(ptr as *const RiCircuitBreakerMetrics);
1218            metrics.failure_count as jlong
1219        }
1220    } else {
1221        0
1222    }
1223}
1224
1225#[no_mangle]
1226pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerMetrics_getSuccessCount0(
1227    _env: JNIEnv,
1228    _class: JClass,
1229    ptr: jlong,
1230) -> jlong {
1231    if ptr != 0 {
1232        unsafe {
1233            let metrics = &*(ptr as *const RiCircuitBreakerMetrics);
1234            metrics.success_count as jlong
1235        }
1236    } else {
1237        0
1238    }
1239}
1240
1241#[no_mangle]
1242pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerMetrics_getConsecutiveFailures0(
1243    _env: JNIEnv,
1244    _class: JClass,
1245    ptr: jlong,
1246) -> jlong {
1247    if ptr != 0 {
1248        unsafe {
1249            let metrics = &*(ptr as *const RiCircuitBreakerMetrics);
1250            metrics.consecutive_failures as jlong
1251        }
1252    } else {
1253        0
1254    }
1255}
1256
1257#[no_mangle]
1258pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreakerMetrics_getConsecutiveSuccesses0(
1259    _env: JNIEnv,
1260    _class: JClass,
1261    ptr: jlong,
1262) -> jlong {
1263    if ptr != 0 {
1264        unsafe {
1265            let metrics = &*(ptr as *const RiCircuitBreakerMetrics);
1266            metrics.consecutive_successes as jlong
1267        }
1268    } else {
1269        0
1270    }
1271}
1272
1273// ============================================================================
1274// RiCircuitBreaker
1275// ============================================================================
1276
1277#[no_mangle]
1278pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_new0(
1279    _env: JNIEnv,
1280    _class: JClass,
1281    config_ptr: jlong,
1282) -> jlong {
1283    let config = if config_ptr != 0 {
1284        unsafe { (*(config_ptr as *const RiCircuitBreakerConfig)).clone() }
1285    } else {
1286        RiCircuitBreakerConfig::default()
1287    };
1288    let cb = Box::new(RiCircuitBreaker::new(config));
1289    Box::into_raw(cb) as jlong
1290}
1291
1292#[no_mangle]
1293pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_free0(
1294    _env: JNIEnv,
1295    _class: JClass,
1296    ptr: jlong,
1297) {
1298    if ptr != 0 {
1299        unsafe {
1300            let _ = Box::from_raw(ptr as *mut RiCircuitBreaker);
1301        }
1302    }
1303}
1304
1305#[no_mangle]
1306pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_allowRequest0(
1307    _env: JNIEnv,
1308    _class: JClass,
1309    ptr: jlong,
1310) -> jboolean {
1311    if ptr != 0 {
1312        unsafe {
1313            let cb = &*(ptr as *const RiCircuitBreaker);
1314            cb.allow_request() as jboolean
1315        }
1316    } else {
1317        0
1318    }
1319}
1320
1321#[no_mangle]
1322pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_recordSuccess0(
1323    _env: JNIEnv,
1324    _class: JClass,
1325    ptr: jlong,
1326) {
1327    if ptr != 0 {
1328        unsafe {
1329            let cb = &*(ptr as *const RiCircuitBreaker);
1330            cb.record_success();
1331        }
1332    }
1333}
1334
1335#[no_mangle]
1336pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_recordFailure0(
1337    _env: JNIEnv,
1338    _class: JClass,
1339    ptr: jlong,
1340) {
1341    if ptr != 0 {
1342        unsafe {
1343            let cb = &*(ptr as *const RiCircuitBreaker);
1344            cb.record_failure();
1345        }
1346    }
1347}
1348
1349#[no_mangle]
1350pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_getState0(
1351    _env: JNIEnv,
1352    _class: JClass,
1353    ptr: jlong,
1354) -> jint {
1355    if ptr != 0 {
1356        unsafe {
1357            let cb = &*(ptr as *const RiCircuitBreaker);
1358            match cb.get_state() {
1359                RiCircuitBreakerState::Closed => 0,
1360                RiCircuitBreakerState::Open => 1,
1361                RiCircuitBreakerState::HalfOpen => 2,
1362            }
1363        }
1364    } else {
1365        0
1366    }
1367}
1368
1369#[no_mangle]
1370pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_getStats0(
1371    _env: JNIEnv,
1372    _class: JClass,
1373    ptr: jlong,
1374) -> jlong {
1375    if ptr != 0 {
1376        unsafe {
1377            let cb = &*(ptr as *const RiCircuitBreaker);
1378            let stats = cb.get_stats();
1379            Box::into_raw(Box::new(stats)) as jlong
1380        }
1381    } else {
1382        0
1383    }
1384}
1385
1386#[no_mangle]
1387pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_getConfig0(
1388    _env: JNIEnv,
1389    _class: JClass,
1390    ptr: jlong,
1391) -> jlong {
1392    if ptr != 0 {
1393        unsafe {
1394            let cb = &*(ptr as *const RiCircuitBreaker);
1395            let config = cb.get_config();
1396            Box::into_raw(Box::new(config)) as jlong
1397        }
1398    } else {
1399        0
1400    }
1401}
1402
1403#[no_mangle]
1404pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_reset0(
1405    _env: JNIEnv,
1406    _class: JClass,
1407    ptr: jlong,
1408) {
1409    if ptr != 0 {
1410        unsafe {
1411            let cb = &*(ptr as *const RiCircuitBreaker);
1412            cb.reset();
1413        }
1414    }
1415}
1416
1417#[no_mangle]
1418pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_forceOpen0(
1419    _env: JNIEnv,
1420    _class: JClass,
1421    ptr: jlong,
1422) {
1423    if ptr != 0 {
1424        unsafe {
1425            let cb = &*(ptr as *const RiCircuitBreaker);
1426            cb.force_open();
1427        }
1428    }
1429}
1430
1431#[no_mangle]
1432pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_forceClose0(
1433    _env: JNIEnv,
1434    _class: JClass,
1435    ptr: jlong,
1436) {
1437    if ptr != 0 {
1438        unsafe {
1439            let cb = &*(ptr as *const RiCircuitBreaker);
1440            cb.force_close();
1441        }
1442    }
1443}
1444
1445#[no_mangle]
1446pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_getFailureRate0(
1447    _env: JNIEnv,
1448    _class: JClass,
1449    ptr: jlong,
1450) -> jdouble {
1451    if ptr != 0 {
1452        unsafe {
1453            let cb = &*(ptr as *const RiCircuitBreaker);
1454            cb.failure_rate()
1455        }
1456    } else {
1457        0.0
1458    }
1459}
1460
1461#[no_mangle]
1462pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_getSuccessRate0(
1463    _env: JNIEnv,
1464    _class: JClass,
1465    ptr: jlong,
1466) -> jdouble {
1467    if ptr != 0 {
1468        unsafe {
1469            let cb = &*(ptr as *const RiCircuitBreaker);
1470            cb.success_rate()
1471        }
1472    } else {
1473        0.0
1474    }
1475}
1476
1477#[no_mangle]
1478pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_getTotalRequests0(
1479    _env: JNIEnv,
1480    _class: JClass,
1481    ptr: jlong,
1482) -> jlong {
1483    if ptr != 0 {
1484        unsafe {
1485            let cb = &*(ptr as *const RiCircuitBreaker);
1486            cb.total_requests() as jlong
1487        }
1488    } else {
1489        0
1490    }
1491}
1492
1493#[no_mangle]
1494pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_isOpen0(
1495    _env: JNIEnv,
1496    _class: JClass,
1497    ptr: jlong,
1498) -> jboolean {
1499    if ptr != 0 {
1500        unsafe {
1501            let cb = &*(ptr as *const RiCircuitBreaker);
1502            cb.is_open() as jboolean
1503        }
1504    } else {
1505        0
1506    }
1507}
1508
1509#[no_mangle]
1510pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_isClosed0(
1511    _env: JNIEnv,
1512    _class: JClass,
1513    ptr: jlong,
1514) -> jboolean {
1515    if ptr != 0 {
1516        unsafe {
1517            let cb = &*(ptr as *const RiCircuitBreaker);
1518            cb.is_closed() as jboolean
1519        }
1520    } else {
1521        0
1522    }
1523}
1524
1525#[no_mangle]
1526pub extern "system" fn Java_com_dunimd_ri_gateway_RiCircuitBreaker_isHalfOpen0(
1527    _env: JNIEnv,
1528    _class: JClass,
1529    ptr: jlong,
1530) -> jboolean {
1531    if ptr != 0 {
1532        unsafe {
1533            let cb = &*(ptr as *const RiCircuitBreaker);
1534            cb.is_half_open() as jboolean
1535        }
1536    } else {
1537        0
1538    }
1539}
1540
1541// ============================================================================
1542// RiBackendServer
1543// ============================================================================
1544
1545#[no_mangle]
1546pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_new0(
1547    mut env: JNIEnv,
1548    _class: JClass,
1549    id: JString,
1550    url: JString,
1551) -> jlong {
1552    let id_str: String = match env.get_string(&id) {
1553        Ok(s) => s.into(),
1554        Err(_) => {
1555            crate::java::exception::throw_ri_error(&mut env, "Invalid id string");
1556            return 0;
1557        }
1558    };
1559    let url_str: String = match env.get_string(&url) {
1560        Ok(s) => s.into(),
1561        Err(_) => {
1562            crate::java::exception::throw_ri_error(&mut env, "Invalid url string");
1563            return 0;
1564        }
1565    };
1566    let server = Box::new(RiBackendServer::new(id_str, url_str));
1567    Box::into_raw(server) as jlong
1568}
1569
1570#[no_mangle]
1571pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_free0(
1572    _env: JNIEnv,
1573    _class: JClass,
1574    ptr: jlong,
1575) {
1576    if ptr != 0 {
1577        unsafe {
1578            let _ = Box::from_raw(ptr as *mut RiBackendServer);
1579        }
1580    }
1581}
1582
1583#[no_mangle]
1584pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_getId0(
1585    env: JNIEnv,
1586    _class: JClass,
1587    ptr: jlong,
1588) -> jstring {
1589    if ptr != 0 {
1590        unsafe {
1591            let server = &*(ptr as *const RiBackendServer);
1592            match env.new_string(&server.id) {
1593            Ok(s) => s.into_raw(),
1594            Err(_) => std::ptr::null_mut(),
1595        }
1596        }
1597    } else {
1598        std::ptr::null_mut()
1599    }
1600}
1601
1602#[no_mangle]
1603pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_getUrl0(
1604    env: JNIEnv,
1605    _class: JClass,
1606    ptr: jlong,
1607) -> jstring {
1608    if ptr != 0 {
1609        unsafe {
1610            let server = &*(ptr as *const RiBackendServer);
1611            match env.new_string(&server.url) {
1612            Ok(s) => s.into_raw(),
1613            Err(_) => std::ptr::null_mut(),
1614        }
1615        }
1616    } else {
1617        std::ptr::null_mut()
1618    }
1619}
1620
1621#[no_mangle]
1622pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_getWeight0(
1623    _env: JNIEnv,
1624    _class: JClass,
1625    ptr: jlong,
1626) -> jint {
1627    if ptr != 0 {
1628        unsafe {
1629            let server = &*(ptr as *const RiBackendServer);
1630            server.weight as jint
1631        }
1632    } else {
1633        0
1634    }
1635}
1636
1637#[no_mangle]
1638pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_setWeight0(
1639    _env: JNIEnv,
1640    _class: JClass,
1641    ptr: jlong,
1642    weight: jint,
1643) {
1644    if ptr != 0 {
1645        unsafe {
1646            let server = &mut *(ptr as *mut RiBackendServer);
1647            server.weight = weight as u32;
1648        }
1649    }
1650}
1651
1652#[no_mangle]
1653pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_getMaxConnections0(
1654    _env: JNIEnv,
1655    _class: JClass,
1656    ptr: jlong,
1657) -> jint {
1658    if ptr != 0 {
1659        unsafe {
1660            let server = &*(ptr as *const RiBackendServer);
1661            server.max_connections as jint
1662        }
1663    } else {
1664        0
1665    }
1666}
1667
1668#[no_mangle]
1669pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_setMaxConnections0(
1670    _env: JNIEnv,
1671    _class: JClass,
1672    ptr: jlong,
1673    max_connections: jint,
1674) {
1675    if ptr != 0 {
1676        unsafe {
1677            let server = &mut *(ptr as *mut RiBackendServer);
1678            server.max_connections = max_connections as usize;
1679        }
1680    }
1681}
1682
1683#[no_mangle]
1684pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_getHealthCheckPath0(
1685    env: JNIEnv,
1686    _class: JClass,
1687    ptr: jlong,
1688) -> jstring {
1689    if ptr != 0 {
1690        unsafe {
1691            let server = &*(ptr as *const RiBackendServer);
1692            match env.new_string(&server.health_check_path) {
1693            Ok(s) => s.into_raw(),
1694            Err(_) => std::ptr::null_mut(),
1695        }
1696        }
1697    } else {
1698        std::ptr::null_mut()
1699    }
1700}
1701
1702#[no_mangle]
1703pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_setHealthCheckPath0(
1704    mut env: JNIEnv,
1705    _class: JClass,
1706    ptr: jlong,
1707    path: JString,
1708) {
1709    if ptr != 0 {
1710        let path_str: String = match env.get_string(&path) {
1711            Ok(s) => s.into(),
1712            Err(_) => {
1713                crate::java::exception::throw_ri_error(&mut env, "Invalid path string");
1714                return;
1715            }
1716        };
1717        unsafe {
1718            let server = &mut *(ptr as *mut RiBackendServer);
1719            server.health_check_path = path_str;
1720        }
1721    }
1722}
1723
1724#[no_mangle]
1725pub extern "system" fn Java_com_dunimd_ri_gateway_RiBackendServer_isHealthy0(
1726    _env: JNIEnv,
1727    _class: JClass,
1728    ptr: jlong,
1729) -> jboolean {
1730    if ptr != 0 {
1731        unsafe {
1732            let server = &*(ptr as *const RiBackendServer);
1733            server.is_healthy as jboolean
1734        }
1735    } else {
1736        0
1737    }
1738}
1739
1740// ============================================================================
1741// RiLoadBalancerServerStats
1742// ============================================================================
1743
1744#[no_mangle]
1745pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancerServerStats_new0(
1746    _env: JNIEnv,
1747    _class: JClass,
1748    active_connections: jlong,
1749    total_requests: jlong,
1750    failed_requests: jlong,
1751    response_time_ms: jlong,
1752) -> jlong {
1753    let stats = Box::new(RiLoadBalancerServerStats {
1754        active_connections: active_connections as usize,
1755        total_requests: total_requests as usize,
1756        failed_requests: failed_requests as usize,
1757        response_time_ms: response_time_ms as usize,
1758    });
1759    Box::into_raw(stats) as jlong
1760}
1761
1762#[no_mangle]
1763pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancerServerStats_free0(
1764    _env: JNIEnv,
1765    _class: JClass,
1766    ptr: jlong,
1767) {
1768    if ptr != 0 {
1769        unsafe {
1770            let _ = Box::from_raw(ptr as *mut RiLoadBalancerServerStats);
1771        }
1772    }
1773}
1774
1775#[no_mangle]
1776pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancerServerStats_getActiveConnections0(
1777    _env: JNIEnv,
1778    _class: JClass,
1779    ptr: jlong,
1780) -> jlong {
1781    if ptr != 0 {
1782        unsafe {
1783            let stats = &*(ptr as *const RiLoadBalancerServerStats);
1784            stats.active_connections as jlong
1785        }
1786    } else {
1787        0
1788    }
1789}
1790
1791#[no_mangle]
1792pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancerServerStats_getTotalRequests0(
1793    _env: JNIEnv,
1794    _class: JClass,
1795    ptr: jlong,
1796) -> jlong {
1797    if ptr != 0 {
1798        unsafe {
1799            let stats = &*(ptr as *const RiLoadBalancerServerStats);
1800            stats.total_requests as jlong
1801        }
1802    } else {
1803        0
1804    }
1805}
1806
1807#[no_mangle]
1808pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancerServerStats_getFailedRequests0(
1809    _env: JNIEnv,
1810    _class: JClass,
1811    ptr: jlong,
1812) -> jlong {
1813    if ptr != 0 {
1814        unsafe {
1815            let stats = &*(ptr as *const RiLoadBalancerServerStats);
1816            stats.failed_requests as jlong
1817        }
1818    } else {
1819        0
1820    }
1821}
1822
1823#[no_mangle]
1824pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancerServerStats_getResponseTimeMs0(
1825    _env: JNIEnv,
1826    _class: JClass,
1827    ptr: jlong,
1828) -> jlong {
1829    if ptr != 0 {
1830        unsafe {
1831            let stats = &*(ptr as *const RiLoadBalancerServerStats);
1832            stats.response_time_ms as jlong
1833        }
1834    } else {
1835        0
1836    }
1837}
1838
1839// ============================================================================
1840// RiLoadBalancer
1841// ============================================================================
1842
1843#[no_mangle]
1844pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_new0(
1845    _env: JNIEnv,
1846    _class: JClass,
1847    strategy: jint,
1848) -> jlong {
1849    let strategy_enum = match strategy {
1850        0 => RiLoadBalancerStrategy::RoundRobin,
1851        1 => RiLoadBalancerStrategy::WeightedRoundRobin,
1852        2 => RiLoadBalancerStrategy::LeastConnections,
1853        3 => RiLoadBalancerStrategy::Random,
1854        4 => RiLoadBalancerStrategy::IpHash,
1855        5 => RiLoadBalancerStrategy::LeastResponseTime,
1856        6 => RiLoadBalancerStrategy::ConsistentHash,
1857        _ => RiLoadBalancerStrategy::RoundRobin,
1858    };
1859    let lb = Box::new(RiLoadBalancer::new(strategy_enum));
1860    Box::into_raw(lb) as jlong
1861}
1862
1863#[no_mangle]
1864pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_free0(
1865    _env: JNIEnv,
1866    _class: JClass,
1867    ptr: jlong,
1868) {
1869    if ptr != 0 {
1870        unsafe {
1871            let _ = Box::from_raw(ptr as *mut RiLoadBalancer);
1872        }
1873    }
1874}
1875
1876#[no_mangle]
1877pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_addServer0(
1878    _env: JNIEnv,
1879    _class: JClass,
1880    ptr: jlong,
1881    server_ptr: jlong,
1882) {
1883    if ptr != 0 && server_ptr != 0 {
1884        unsafe {
1885            let lb = &*(ptr as *const RiLoadBalancer);
1886            // Clone the server: the Java-side RiBackendServer wrapper keeps ownership
1887            // of its own native pointer and may free it via close(), so we must not
1888            // consume it (Box::from_raw here would cause a double-free on close()).
1889            let server = &*(server_ptr as *const RiBackendServer);
1890            futures::executor::block_on(async {
1891                let _ = lb.add_server(server.clone()).await;
1892            });
1893        }
1894    }
1895}
1896
1897#[no_mangle]
1898pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_removeServer0(
1899    mut env: JNIEnv,
1900    _class: JClass,
1901    ptr: jlong,
1902    server_id: JString,
1903) -> jboolean {
1904    if ptr != 0 {
1905        let server_id_str: String = match env.get_string(&server_id) {
1906            Ok(s) => s.into(),
1907            Err(_) => {
1908                crate::java::exception::throw_ri_error(&mut env, "Invalid server_id string");
1909                return 0;
1910            }
1911        };
1912        unsafe {
1913            let lb = &*(ptr as *const RiLoadBalancer);
1914            futures::executor::block_on(async { lb.remove_server(&server_id_str).await })
1915                as jboolean
1916        }
1917    } else {
1918        0
1919    }
1920}
1921
1922#[no_mangle]
1923pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_selectBackend0(
1924    mut env: JNIEnv,
1925    _class: JClass,
1926    ptr: jlong,
1927    client_ip: JString,
1928) -> jlong {
1929    if ptr != 0 {
1930        let client_ip_str: Option<String> = if client_ip.is_null() {
1931            None
1932        } else {
1933            env.get_string(&client_ip).ok().map(|s| s.into())
1934        };
1935        unsafe {
1936            let lb = &*(ptr as *const RiLoadBalancer);
1937            futures::executor::block_on(async {
1938                match lb.select_server(client_ip_str.as_deref()).await {
1939                    Ok(server) => Box::into_raw(Box::new(server)) as jlong,
1940                    Err(_) => 0,
1941                }
1942            })
1943        }
1944    } else {
1945        0
1946    }
1947}
1948
1949#[no_mangle]
1950pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_releaseServer0(
1951    mut env: JNIEnv,
1952    _class: JClass,
1953    ptr: jlong,
1954    server_id: JString,
1955) {
1956    if ptr != 0 {
1957        let server_id_str: String = match env.get_string(&server_id) {
1958            Ok(s) => s.into(),
1959            Err(_) => {
1960                crate::java::exception::throw_ri_error(&mut env, "Invalid server_id string");
1961                return;
1962            }
1963        };
1964        unsafe {
1965            let lb = &*(ptr as *const RiLoadBalancer);
1966            futures::executor::block_on(async {
1967                lb.release_server(&server_id_str).await;
1968            });
1969        }
1970    }
1971}
1972
1973#[no_mangle]
1974pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_recordServerFailure0(
1975    mut env: JNIEnv,
1976    _class: JClass,
1977    ptr: jlong,
1978    server_id: JString,
1979) {
1980    if ptr != 0 {
1981        let server_id_str: String = match env.get_string(&server_id) {
1982            Ok(s) => s.into(),
1983            Err(_) => {
1984                crate::java::exception::throw_ri_error(&mut env, "Invalid server_id string");
1985                return;
1986            }
1987        };
1988        unsafe {
1989            let lb = &*(ptr as *const RiLoadBalancer);
1990            futures::executor::block_on(async {
1991                lb.record_server_failure(&server_id_str).await;
1992            });
1993        }
1994    }
1995}
1996
1997#[no_mangle]
1998pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_recordResponseTime0(
1999    mut env: JNIEnv,
2000    _class: JClass,
2001    ptr: jlong,
2002    server_id: JString,
2003    response_time_ms: jlong,
2004) {
2005    if ptr != 0 {
2006        let server_id_str: String = match env.get_string(&server_id) {
2007            Ok(s) => s.into(),
2008            Err(_) => {
2009                crate::java::exception::throw_ri_error(&mut env, "Invalid server_id string");
2010                return;
2011            }
2012        };
2013        unsafe {
2014            let lb = &*(ptr as *const RiLoadBalancer);
2015            futures::executor::block_on(async {
2016                lb.record_response_time(&server_id_str, response_time_ms as u64)
2017                    .await;
2018            });
2019        }
2020    }
2021}
2022
2023#[no_mangle]
2024pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_getServerStats0(
2025    mut env: JNIEnv,
2026    _class: JClass,
2027    ptr: jlong,
2028    server_id: JString,
2029) -> jlong {
2030    if ptr != 0 {
2031        let server_id_str: String = match env.get_string(&server_id) {
2032            Ok(s) => s.into(),
2033            Err(_) => {
2034                crate::java::exception::throw_ri_error(&mut env, "Invalid server_id string");
2035                return 0;
2036            }
2037        };
2038        unsafe {
2039            let lb = &*(ptr as *const RiLoadBalancer);
2040            futures::executor::block_on(async {
2041                match lb.get_server_stats(&server_id_str).await {
2042                    Some(stats) => Box::into_raw(Box::new(stats)) as jlong,
2043                    None => 0,
2044                }
2045            })
2046        }
2047    } else {
2048        0
2049    }
2050}
2051
2052#[no_mangle]
2053pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_markServerHealthy0(
2054    mut env: JNIEnv,
2055    _class: JClass,
2056    ptr: jlong,
2057    server_id: JString,
2058    healthy: jboolean,
2059) {
2060    if ptr != 0 {
2061        let server_id_str: String = match env.get_string(&server_id) {
2062            Ok(s) => s.into(),
2063            Err(_) => {
2064                crate::java::exception::throw_ri_error(&mut env, "Invalid server_id string");
2065                return;
2066            }
2067        };
2068        unsafe {
2069            let lb = &*(ptr as *const RiLoadBalancer);
2070            futures::executor::block_on(async {
2071                lb.mark_server_healthy(&server_id_str, healthy != 0).await;
2072            });
2073        }
2074    }
2075}
2076
2077#[no_mangle]
2078pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_performHealthCheck0(
2079    mut env: JNIEnv,
2080    _class: JClass,
2081    ptr: jlong,
2082    server_id: JString,
2083) -> jboolean {
2084    if ptr != 0 {
2085        let server_id_str: String = match env.get_string(&server_id) {
2086            Ok(s) => s.into(),
2087            Err(_) => {
2088                crate::java::exception::throw_ri_error(&mut env, "Invalid server_id string");
2089                return 0;
2090            }
2091        };
2092        unsafe {
2093            let lb = &*(ptr as *const RiLoadBalancer);
2094            futures::executor::block_on(async { lb.perform_health_check(&server_id_str).await })
2095                as jboolean
2096        }
2097    } else {
2098        0
2099    }
2100}
2101
2102#[no_mangle]
2103pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_getServerCount0(
2104    _env: JNIEnv,
2105    _class: JClass,
2106    ptr: jlong,
2107) -> jint {
2108    if ptr != 0 {
2109        unsafe {
2110            let lb = &*(ptr as *const RiLoadBalancer);
2111            futures::executor::block_on(async { lb.get_server_count().await as jint })
2112        }
2113    } else {
2114        0
2115    }
2116}
2117
2118#[no_mangle]
2119pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_getHealthyServerCount0(
2120    _env: JNIEnv,
2121    _class: JClass,
2122    ptr: jlong,
2123) -> jint {
2124    if ptr != 0 {
2125        unsafe {
2126            let lb = &*(ptr as *const RiLoadBalancer);
2127            futures::executor::block_on(async { lb.get_healthy_server_count().await as jint })
2128        }
2129    } else {
2130        0
2131    }
2132}
2133
2134#[no_mangle]
2135pub extern "system" fn Java_com_dunimd_ri_gateway_RiLoadBalancer_getStrategy0(
2136    _env: JNIEnv,
2137    _class: JClass,
2138    ptr: jlong,
2139) -> jint {
2140    if ptr != 0 {
2141        unsafe {
2142            let lb = &*(ptr as *const RiLoadBalancer);
2143            match lb.get_strategy() {
2144                RiLoadBalancerStrategy::RoundRobin => 0,
2145                RiLoadBalancerStrategy::WeightedRoundRobin => 1,
2146                RiLoadBalancerStrategy::LeastConnections => 2,
2147                RiLoadBalancerStrategy::Random => 3,
2148                RiLoadBalancerStrategy::IpHash => 4,
2149                RiLoadBalancerStrategy::LeastResponseTime => 5,
2150                RiLoadBalancerStrategy::ConsistentHash => 6,
2151            }
2152        }
2153    } else {
2154        0
2155    }
2156}