1use jni::JNIEnv;
30use jni::objects::{JClass, JString};
31use jni::sys::{jlong, jboolean, jint, jstring};
32use std::sync::Arc;
33use dashmap::DashSet;
34use std::any::TypeId;
35
36use crate::validation::{
37 RiValidationModule, RiValidationError, RiValidationResult,
38 RiSanitizer, RiSanitizationConfig, RiSchemaValidator,
39};
40use crate::java::exception::check_not_null;
41
42lazy_static::lazy_static! {
43 static ref VALIDATION_MODULE_REGISTRY: DashSet<usize> = DashSet::new();
44 static ref VALIDATION_ERROR_REGISTRY: DashSet<usize> = DashSet::new();
45 static ref VALIDATION_RESULT_REGISTRY: DashSet<usize> = DashSet::new();
46 static ref SANITIZATION_CONFIG_REGISTRY: DashSet<usize> = DashSet::new();
47 static ref SANITIZER_REGISTRY: DashSet<usize> = DashSet::new();
48 static ref SCHEMA_VALIDATOR_REGISTRY: DashSet<usize> = DashSet::new();
49}
50
51fn register_ptr(registry: &DashSet<usize>, ptr: usize) {
52 registry.insert(ptr);
53}
54
55fn unregister_ptr(registry: &DashSet<usize>, ptr: usize) -> bool {
56 registry.remove(&ptr).is_some()
57}
58
59fn is_valid_ptr(registry: &DashSet<usize>, ptr: usize) -> bool {
60 ptr != 0 && registry.contains(&ptr)
61}
62
63#[no_mangle]
68pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_new0(
69 _env: JNIEnv,
70 _class: JClass,
71) -> jlong {
72 let module = Box::new(RiValidationModule::new());
73 let ptr = Box::into_raw(module) as jlong;
74 register_ptr(&VALIDATION_MODULE_REGISTRY, ptr as usize);
75 ptr
76}
77
78#[no_mangle]
79pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_validate0(
80 mut env: JNIEnv,
81 _class: JClass,
82 ptr: jlong,
83 data: JString,
84) -> jlong {
85 if !is_valid_ptr(&VALIDATION_MODULE_REGISTRY, ptr as usize) {
86 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationModule pointer")
87 .unwrap_or(());
88 return 0;
89 }
90
91 let data_str: String = match env.get_string(&data) {
92 Ok(s) => s.into(),
93 Err(_) => {
94 env.throw_new("java/lang/IllegalArgumentException", "Failed to get data string")
95 .unwrap_or(());
96 return 0;
97 }
98 };
99
100 let module = unsafe { &*(ptr as *const RiValidationModule) };
101 let result = Box::new(module.validate(&data_str));
102 let result_ptr = Box::into_raw(result) as jlong;
103 register_ptr(&VALIDATION_RESULT_REGISTRY, result_ptr as usize);
104 result_ptr
105}
106
107#[no_mangle]
108pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_free0(
109 _env: JNIEnv,
110 _class: JClass,
111 ptr: jlong,
112) {
113 if unregister_ptr(&VALIDATION_MODULE_REGISTRY, ptr as usize) {
114 unsafe {
115 let _ = Box::from_raw(ptr as *mut RiValidationModule);
116 }
117 }
118}
119
120#[no_mangle]
125pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getField0<'local>(
126 mut env: JNIEnv<'local>,
127 _class: JClass<'local>,
128 ptr: jlong,
129) -> jstring {
130 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
131 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
132 .unwrap_or(());
133 return std::ptr::null_mut();
134 }
135
136 let error = unsafe { &*(ptr as *const RiValidationError) };
137 match env.new_string(&error.field) {
138 Ok(s) => s.into_raw(),
139 Err(_) => std::ptr::null_mut(),
140 }
141}
142
143#[no_mangle]
144pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getMessage0<'local>(
145 mut env: JNIEnv<'local>,
146 _class: JClass<'local>,
147 ptr: jlong,
148) -> jstring {
149 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
150 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
151 .unwrap_or(());
152 return std::ptr::null_mut();
153 }
154
155 let error = unsafe { &*(ptr as *const RiValidationError) };
156 match env.new_string(&error.message) {
157 Ok(s) => s.into_raw(),
158 Err(_) => std::ptr::null_mut(),
159 }
160}
161
162#[no_mangle]
163pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getCode0<'local>(
164 mut env: JNIEnv<'local>,
165 _class: JClass<'local>,
166 ptr: jlong,
167) -> jstring {
168 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
169 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
170 .unwrap_or(());
171 return std::ptr::null_mut();
172 }
173
174 let error = unsafe { &*(ptr as *const RiValidationError) };
175 match env.new_string(&error.code) {
176 Ok(s) => s.into_raw(),
177 Err(_) => std::ptr::null_mut(),
178 }
179}
180
181#[no_mangle]
182pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getSeverity0(
183 mut env: JNIEnv,
184 _class: JClass,
185 ptr: jlong,
186) -> jint {
187 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
188 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
189 .unwrap_or(());
190 return 0;
191 }
192
193 let error = unsafe { &*(ptr as *const RiValidationError) };
194 error.severity as jint
195}
196
197#[no_mangle]
198pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_free0(
199 _env: JNIEnv,
200 _class: JClass,
201 ptr: jlong,
202) {
203 if unregister_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
204 unsafe {
205 let _ = Box::from_raw(ptr as *mut RiValidationError);
206 }
207 }
208}
209
210#[no_mangle]
215pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationResult_isValid0(
216 mut env: JNIEnv,
217 _class: JClass,
218 ptr: jlong,
219) -> jboolean {
220 if !is_valid_ptr(&VALIDATION_RESULT_REGISTRY, ptr as usize) {
221 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationResult pointer")
222 .unwrap_or(());
223 return 0;
224 }
225
226 let result = unsafe { &*(ptr as *const RiValidationResult) };
227 result.is_valid as jboolean
228}
229
230#[no_mangle]
231pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationResult_getErrors0(
232 mut env: JNIEnv,
233 _class: JClass,
234 ptr: jlong,
235) -> jlong {
236 if !is_valid_ptr(&VALIDATION_RESULT_REGISTRY, ptr as usize) {
237 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationResult pointer")
238 .unwrap_or(());
239 return 0;
240 }
241
242 let result = unsafe { &*(ptr as *const RiValidationResult) };
243 let errors = Box::new(result.errors.clone());
244 let errors_ptr = Box::into_raw(errors) as jlong;
245 register_ptr(&VALIDATION_ERROR_REGISTRY, errors_ptr as usize);
246 errors_ptr
247}
248
249#[no_mangle]
250pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationResult_free0(
251 _env: JNIEnv,
252 _class: JClass,
253 ptr: jlong,
254) {
255 if unregister_ptr(&VALIDATION_RESULT_REGISTRY, ptr as usize) {
256 unsafe {
257 let _ = Box::from_raw(ptr as *mut RiValidationResult);
258 }
259 }
260}
261
262#[no_mangle]
267pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_new0(
268 _env: JNIEnv,
269 _class: JClass,
270) -> jlong {
271 let config = Box::new(RiSanitizationConfig::default());
272 let ptr = Box::into_raw(config) as jlong;
273 register_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize);
274 ptr
275}
276
277#[no_mangle]
278pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isTrimWhitespace0(
279 mut env: JNIEnv,
280 _class: JClass,
281 ptr: jlong,
282) -> jboolean {
283 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
284 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
285 .unwrap_or(());
286 return 0;
287 }
288
289 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
290 config.trim_whitespace as jboolean
291}
292
293#[no_mangle]
294pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setTrimWhitespace0(
295 mut env: JNIEnv,
296 _class: JClass,
297 ptr: jlong,
298 enabled: jboolean,
299) {
300 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
301 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
302 .unwrap_or(());
303 return;
304 }
305
306 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
307 config.trim_whitespace = enabled != 0;
308}
309
310#[no_mangle]
311pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isLowercase0(
312 mut env: JNIEnv,
313 _class: JClass,
314 ptr: jlong,
315) -> jboolean {
316 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
317 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
318 .unwrap_or(());
319 return 0;
320 }
321
322 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
323 config.lowercase as jboolean
324}
325
326#[no_mangle]
327pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setLowercase0(
328 mut env: JNIEnv,
329 _class: JClass,
330 ptr: jlong,
331 enabled: jboolean,
332) {
333 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
334 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
335 .unwrap_or(());
336 return;
337 }
338
339 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
340 config.lowercase = enabled != 0;
341}
342
343#[no_mangle]
344pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isUppercase0(
345 mut env: JNIEnv,
346 _class: JClass,
347 ptr: jlong,
348) -> jboolean {
349 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
350 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
351 .unwrap_or(());
352 return 0;
353 }
354
355 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
356 config.uppercase as jboolean
357}
358
359#[no_mangle]
360pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setUppercase0(
361 mut env: JNIEnv,
362 _class: JClass,
363 ptr: jlong,
364 enabled: jboolean,
365) {
366 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
367 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
368 .unwrap_or(());
369 return;
370 }
371
372 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
373 config.uppercase = enabled != 0;
374}
375
376#[no_mangle]
377pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isRemoveHtmlTags0(
378 mut env: JNIEnv,
379 _class: JClass,
380 ptr: jlong,
381) -> jboolean {
382 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
383 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
384 .unwrap_or(());
385 return 0;
386 }
387
388 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
389 config.remove_html_tags as jboolean
390}
391
392#[no_mangle]
393pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setRemoveHtmlTags0(
394 mut env: JNIEnv,
395 _class: JClass,
396 ptr: jlong,
397 enabled: jboolean,
398) {
399 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
400 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
401 .unwrap_or(());
402 return;
403 }
404
405 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
406 config.remove_html_tags = enabled != 0;
407}
408
409#[no_mangle]
410pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isEscapeSpecialChars0(
411 mut env: JNIEnv,
412 _class: JClass,
413 ptr: jlong,
414) -> jboolean {
415 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
416 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
417 .unwrap_or(());
418 return 0;
419 }
420
421 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
422 config.escape_special_chars as jboolean
423}
424
425#[no_mangle]
426pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setEscapeSpecialChars0(
427 mut env: JNIEnv,
428 _class: JClass,
429 ptr: jlong,
430 enabled: jboolean,
431) {
432 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
433 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
434 .unwrap_or(());
435 return;
436 }
437
438 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
439 config.escape_special_chars = enabled != 0;
440}
441
442#[no_mangle]
443pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_free0(
444 _env: JNIEnv,
445 _class: JClass,
446 ptr: jlong,
447) {
448 if unregister_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
449 unsafe {
450 let _ = Box::from_raw(ptr as *mut RiSanitizationConfig);
451 }
452 }
453}
454
455#[no_mangle]
460pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_new0(
461 _env: JNIEnv,
462 _class: JClass,
463) -> jlong {
464 let sanitizer = Box::new(RiSanitizer::new());
465 let ptr = Box::into_raw(sanitizer) as jlong;
466 register_ptr(&SANITIZER_REGISTRY, ptr as usize);
467 ptr
468}
469
470#[no_mangle]
471pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_newWithConfig0(
472 mut env: JNIEnv,
473 _class: JClass,
474 config_ptr: jlong,
475) -> jlong {
476 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, config_ptr as usize) {
477 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
478 .unwrap_or(());
479 return 0;
480 }
481
482 let config = unsafe { &*(config_ptr as *const RiSanitizationConfig) };
483 let sanitizer = Box::new(RiSanitizer::with_config(config.clone()));
484 let ptr = Box::into_raw(sanitizer) as jlong;
485 register_ptr(&SANITIZER_REGISTRY, ptr as usize);
486 ptr
487}
488
489#[no_mangle]
490pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_sanitize0<'local>(
491 mut env: JNIEnv<'local>,
492 _class: JClass<'local>,
493 ptr: jlong,
494 input: JString,
495) -> jstring {
496 if !is_valid_ptr(&SANITIZER_REGISTRY, ptr as usize) {
497 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizer pointer")
498 .unwrap_or(());
499 return std::ptr::null_mut();
500 }
501
502 let input_str: String = match env.get_string(&input) {
503 Ok(s) => s.into(),
504 Err(_) => {
505 env.throw_new("java/lang/IllegalArgumentException", "Failed to get input string")
506 .unwrap_or(());
507 return std::ptr::null_mut();
508 }
509 };
510
511 let sanitizer = unsafe { &*(ptr as *const RiSanitizer) };
512 let result = sanitizer.sanitize(&input_str);
513 match env.new_string(&result) {
514 Ok(s) => s.into_raw(),
515 Err(_) => std::ptr::null_mut(),
516 }
517}
518
519#[no_mangle]
520pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_sanitizeEmail0<'local>(
521 mut env: JNIEnv<'local>,
522 _class: JClass<'local>,
523 ptr: jlong,
524 input: JString,
525) -> jstring {
526 if !is_valid_ptr(&SANITIZER_REGISTRY, ptr as usize) {
527 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizer pointer")
528 .unwrap_or(());
529 return std::ptr::null_mut();
530 }
531
532 let input_str: String = match env.get_string(&input) {
533 Ok(s) => s.into(),
534 Err(_) => {
535 env.throw_new("java/lang/IllegalArgumentException", "Failed to get input string")
536 .unwrap_or(());
537 return std::ptr::null_mut();
538 }
539 };
540
541 let sanitizer = unsafe { &*(ptr as *const RiSanitizer) };
542 let result = sanitizer.sanitize_email(&input_str);
543 match env.new_string(&result) {
544 Ok(s) => s.into_raw(),
545 Err(_) => std::ptr::null_mut(),
546 }
547}
548
549#[no_mangle]
550pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_sanitizeFilename0<'local>(
551 mut env: JNIEnv<'local>,
552 _class: JClass<'local>,
553 ptr: jlong,
554 input: JString,
555) -> jstring {
556 if !is_valid_ptr(&SANITIZER_REGISTRY, ptr as usize) {
557 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizer pointer")
558 .unwrap_or(());
559 return std::ptr::null_mut();
560 }
561
562 let input_str: String = match env.get_string(&input) {
563 Ok(s) => s.into(),
564 Err(_) => {
565 env.throw_new("java/lang/IllegalArgumentException", "Failed to get input string")
566 .unwrap_or(());
567 return std::ptr::null_mut();
568 }
569 };
570
571 let sanitizer = unsafe { &*(ptr as *const RiSanitizer) };
572 let result = sanitizer.sanitize_filename(&input_str);
573 match env.new_string(&result) {
574 Ok(s) => s.into_raw(),
575 Err(_) => std::ptr::null_mut(),
576 }
577}
578
579#[no_mangle]
580pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_free0(
581 _env: JNIEnv,
582 _class: JClass,
583 ptr: jlong,
584) {
585 if unregister_ptr(&SANITIZER_REGISTRY, ptr as usize) {
586 unsafe {
587 let _ = Box::from_raw(ptr as *mut RiSanitizer);
588 }
589 }
590}
591
592#[no_mangle]
597pub extern "system" fn Java_com_dunimd_ri_validation_RiSchemaValidator_new0(
598 mut env: JNIEnv,
599 _class: JClass,
600 schema_json: JString,
601) -> jlong {
602 let schema_str: String = match env.get_string(&schema_json) {
603 Ok(s) => s.into(),
604 Err(_) => {
605 env.throw_new("java/lang/IllegalArgumentException", "Failed to get schema string")
606 .unwrap_or(());
607 return 0;
608 }
609 };
610
611 match RiSchemaValidator::new(&schema_str) {
612 Ok(validator) => {
613 let ptr = Box::into_raw(Box::new(validator)) as jlong;
614 register_ptr(&SCHEMA_VALIDATOR_REGISTRY, ptr as usize);
615 ptr
616 }
617 Err(e) => {
618 env.throw_new("java/lang/IllegalArgumentException", &format!("Failed to create validator: {}", e))
619 .unwrap_or(());
620 0
621 }
622 }
623}
624
625#[no_mangle]
626pub extern "system" fn Java_com_dunimd_ri_validation_RiSchemaValidator_validate0(
627 mut env: JNIEnv,
628 _class: JClass,
629 ptr: jlong,
630 data_json: JString,
631) -> jlong {
632 if !is_valid_ptr(&SCHEMA_VALIDATOR_REGISTRY, ptr as usize) {
633 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSchemaValidator pointer")
634 .unwrap_or(());
635 return 0;
636 }
637
638 let data_str: String = match env.get_string(&data_json) {
639 Ok(s) => s.into(),
640 Err(_) => {
641 env.throw_new("java/lang/IllegalArgumentException", "Failed to get data string")
642 .unwrap_or(());
643 return 0;
644 }
645 };
646
647 let validator = unsafe { &*(ptr as *const RiSchemaValidator) };
648 let result = Box::new(validator.validate(&data_str));
649 let result_ptr = Box::into_raw(result) as jlong;
650 register_ptr(&VALIDATION_RESULT_REGISTRY, result_ptr as usize);
651 result_ptr
652}
653
654#[no_mangle]
655pub extern "system" fn Java_com_dunimd_ri_validation_RiSchemaValidator_free0(
656 _env: JNIEnv,
657 _class: JClass,
658 ptr: jlong,
659) {
660 if unregister_ptr(&SCHEMA_VALIDATOR_REGISTRY, ptr as usize) {
661 unsafe {
662 let _ = Box::from_raw(ptr as *mut RiSchemaValidator);
663 }
664 }
665}