1- use alloc:: { format, vec, vec:: Vec } ;
1+ use alloc:: { format, string :: ToString , vec, vec:: Vec } ;
22
33use jvm:: {
44 Array , ClassInstanceRef , Jvm , Result ,
55 runtime:: { JavaIoInputStream , JavaLangString } ,
66} ;
77use jvm_class_proto:: { JavaFieldProto , JavaMethodProto } ;
88use jvm_types:: { ClassAccessFlags , FieldAccessFlags , MethodAccessFlags } ;
9+ use percent_encoding:: utf8_percent_encode;
910
1011use crate :: {
1112 FileType , RuntimeClassProto , RuntimeContext ,
1213 classes:: java:: {
1314 lang:: { Class , ClassLoader , String } ,
14- net:: { JarURLConnection , URL } ,
15+ net:: { JarURLConnection , URL , URL_PATH , decode_url_path } ,
1516 util:: jar:: JarEntry ,
1617 } ,
1718} ;
@@ -133,16 +134,17 @@ impl URLClassLoader {
133134 for url in urls {
134135 let file = jvm. invoke_virtual ( & url, "java/net/URL" , "getFile" , "()Ljava/lang/String;" , ( ) ) . await ?;
135136 let file = JavaLangString :: to_rust_string ( jvm, & file) . await ?;
137+ let path = decode_url_path ( jvm, & file) . await ?;
136138
137- let metadata = runtime. metadata ( & file ) . await ;
138- if file . ends_with ( '/' ) || file . is_empty ( ) || metadata. as_ref ( ) . is_ok_and ( |metadata| metadata. r#type == FileType :: Directory ) {
139+ let metadata = runtime. metadata ( & path ) . await ;
140+ if path . ends_with ( '/' ) || path . is_empty ( ) || metadata. as_ref ( ) . is_ok_and ( |metadata| metadata. r#type == FileType :: Directory ) {
139141 // directory
140- let final_path = if file . is_empty ( ) {
142+ let final_path = if path . is_empty ( ) {
141143 name_str. clone ( )
142- } else if file . ends_with ( '/' ) {
143- format ! ( "{file }{name_str}" )
144+ } else if path . ends_with ( '/' ) {
145+ format ! ( "{path }{name_str}" )
144146 } else {
145- format ! ( "{file }/{name_str}" )
147+ format ! ( "{path }/{name_str}" )
146148 } ;
147149
148150 if runtime. metadata ( & final_path) . await . is_ok ( ) {
@@ -153,7 +155,7 @@ impl URLClassLoader {
153155 (
154156 JavaLangString :: from_rust_string ( jvm, "file" ) . await ?,
155157 JavaLangString :: from_rust_string ( jvm, "" ) . await ?,
156- JavaLangString :: from_rust_string ( jvm, & final_path) . await ?,
158+ JavaLangString :: from_rust_string ( jvm, & utf8_percent_encode ( & final_path, URL_PATH ) . to_string ( ) ) . await ?,
157159 ) ,
158160 )
159161 . await ?;
@@ -166,7 +168,7 @@ impl URLClassLoader {
166168 // treat as jar
167169 let name_str = name_str. trim_start_matches ( '/' ) ;
168170
169- let jar_url_str = format ! ( "jar:file:{file}!/{name_str}" ) ; // TODO url might not be file
171+ let jar_url_str = format ! ( "jar:file:{file}!/{}" , utf8_percent_encode ( name_str , URL_PATH ) ) ; // TODO url might not be file
170172 let jar_url = JavaLangString :: from_rust_string ( jvm, & jar_url_str) . await ?;
171173 let jar_url = jvm. new_class ( "java/net/URL" , "(Ljava/lang/String;)V" , ( jar_url, ) ) . await ?;
172174 let connection: ClassInstanceRef < JarURLConnection > = jvm
0 commit comments