From 68da2a421b29e74f67de1687f35f1b7cef1cb38e Mon Sep 17 00:00:00 2001 From: Anikate-De Date: Tue, 4 Jun 2024 03:23:12 +0530 Subject: [PATCH 1/5] generate bindings for `ConnectionPool` & `Dispatcher` (pkgs/ok_http/) --- pkgs/ok_http/jnigen.yaml | 3 + pkgs/ok_http/lib/src/jni/bindings.dart | 580 ++++++++++++++++++++++++- 2 files changed, 577 insertions(+), 6 deletions(-) diff --git a/pkgs/ok_http/jnigen.yaml b/pkgs/ok_http/jnigen.yaml index 6243a04bce..de56e8937d 100644 --- a/pkgs/ok_http/jnigen.yaml +++ b/pkgs/ok_http/jnigen.yaml @@ -23,6 +23,8 @@ classes: - "okhttp3.Call" - "okhttp3.Headers" - "okhttp3.Callback" + - "okhttp3.ConnectionPool" + - "okhttp3.Dispatcher" # Exclude the deprecated methods listed below # They cause syntax errors during the `dart format` step of JNIGen. @@ -76,6 +78,7 @@ exclude: - 'okhttp3.OkHttpClient\$Builder#-addNetworkInterceptor' - 'okhttp3.Headers\$Companion#-deprecated_of' - "okhttp3.Headers#-deprecated_size" + - "okhttp3.Dispatcher#-deprecated_executorService" class_path: - "jar/okhttp-4.12.0.jar" diff --git a/pkgs/ok_http/lib/src/jni/bindings.dart b/pkgs/ok_http/lib/src/jni/bindings.dart index 64b23fd85e..5c17892b3f 100644 --- a/pkgs/ok_http/lib/src/jni/bindings.dart +++ b/pkgs/ok_http/lib/src/jni/bindings.dart @@ -4334,7 +4334,7 @@ class OkHttpClient_Builder extends jni.JObject { /// from: public final okhttp3.OkHttpClient$Builder dispatcher(okhttp3.Dispatcher dispatcher) /// The returned object must be released after use, by calling the [release] method. OkHttpClient_Builder dispatcher( - jni.JObject dispatcher, + Dispatcher dispatcher, ) { return _dispatcher(reference.pointer, _id_dispatcher as jni.JMethodIDPtr, dispatcher.reference.pointer) @@ -4360,7 +4360,7 @@ class OkHttpClient_Builder extends jni.JObject { /// from: public final okhttp3.OkHttpClient$Builder connectionPool(okhttp3.ConnectionPool connectionPool) /// The returned object must be released after use, by calling the [release] method. OkHttpClient_Builder connectionPool( - jni.JObject connectionPool, + ConnectionPool connectionPool, ) { return _connectionPool( reference.pointer, @@ -5463,9 +5463,9 @@ class OkHttpClient extends jni.JObject { /// from: public final okhttp3.Dispatcher dispatcher() /// The returned object must be released after use, by calling the [release] method. - jni.JObject dispatcher() { + Dispatcher dispatcher() { return _dispatcher(reference.pointer, _id_dispatcher as jni.JMethodIDPtr) - .object(const jni.JObjectType()); + .object(const $DispatcherType()); } static final _id_connectionPool = _class.instanceMethodId( @@ -5487,10 +5487,10 @@ class OkHttpClient extends jni.JObject { /// from: public final okhttp3.ConnectionPool connectionPool() /// The returned object must be released after use, by calling the [release] method. - jni.JObject connectionPool() { + ConnectionPool connectionPool() { return _connectionPool( reference.pointer, _id_connectionPool as jni.JMethodIDPtr) - .object(const jni.JObjectType()); + .object(const $ConnectionPoolType()); } static final _id_interceptors = _class.instanceMethodId( @@ -8138,3 +8138,571 @@ final class $CallbackType extends jni.JObjType { return other.runtimeType == ($CallbackType) && other is $CallbackType; } } + +/// from: okhttp3.ConnectionPool +class ConnectionPool extends jni.JObject { + @override + late final jni.JObjType $type = type; + + ConnectionPool.fromReference( + jni.JReference reference, + ) : super.fromReference(reference); + + static final _class = jni.JClass.forName(r"okhttp3/ConnectionPool"); + + /// The type which includes information such as the signature of this class. + static const type = $ConnectionPoolType(); + static final _id_new0 = _class.constructorId( + r"(Lokhttp3/internal/connection/RealConnectionPool;)V", + ); + + static final _new0 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_NewObject") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public void (okhttp3.internal.connection.RealConnectionPool realConnectionPool) + /// The returned object must be released after use, by calling the [release] method. + factory ConnectionPool( + jni.JObject realConnectionPool, + ) { + return ConnectionPool.fromReference(_new0(_class.reference.pointer, + _id_new0 as jni.JMethodIDPtr, realConnectionPool.reference.pointer) + .reference); + } + + static final _id_new1 = _class.constructorId( + r"(IJLjava/util/concurrent/TimeUnit;)V", + ); + + static final _new1 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs< + ( + ffi.Int64, + ffi.Int64, + ffi.Pointer + )>)>>("globalEnv_NewObject") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, int, + int, ffi.Pointer)>(); + + /// from: public void (int i, long j, java.util.concurrent.TimeUnit timeUnit) + /// The returned object must be released after use, by calling the [release] method. + factory ConnectionPool.new1( + int i, + int j, + jni.JObject timeUnit, + ) { + return ConnectionPool.fromReference(_new1(_class.reference.pointer, + _id_new1 as jni.JMethodIDPtr, i, j, timeUnit.reference.pointer) + .reference); + } + + static final _id_new2 = _class.constructorId( + r"()V", + ); + + static final _new2 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_NewObject") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public void () + /// The returned object must be released after use, by calling the [release] method. + factory ConnectionPool.new2() { + return ConnectionPool.fromReference( + _new2(_class.reference.pointer, _id_new2 as jni.JMethodIDPtr) + .reference); + } + + static final _id_idleConnectionCount = _class.instanceMethodId( + r"idleConnectionCount", + r"()I", + ); + + static final _idleConnectionCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int idleConnectionCount() + int idleConnectionCount() { + return _idleConnectionCount( + reference.pointer, _id_idleConnectionCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_connectionCount = _class.instanceMethodId( + r"connectionCount", + r"()I", + ); + + static final _connectionCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int connectionCount() + int connectionCount() { + return _connectionCount( + reference.pointer, _id_connectionCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_evictAll = _class.instanceMethodId( + r"evictAll", + r"()V", + ); + + static final _evictAll = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final void evictAll() + void evictAll() { + _evictAll(reference.pointer, _id_evictAll as jni.JMethodIDPtr).check(); + } +} + +final class $ConnectionPoolType extends jni.JObjType { + const $ConnectionPoolType(); + + @override + String get signature => r"Lokhttp3/ConnectionPool;"; + + @override + ConnectionPool fromReference(jni.JReference reference) => + ConnectionPool.fromReference(reference); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($ConnectionPoolType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($ConnectionPoolType) && + other is $ConnectionPoolType; + } +} + +/// from: okhttp3.Dispatcher +class Dispatcher extends jni.JObject { + @override + late final jni.JObjType $type = type; + + Dispatcher.fromReference( + jni.JReference reference, + ) : super.fromReference(reference); + + static final _class = jni.JClass.forName(r"okhttp3/Dispatcher"); + + /// The type which includes information such as the signature of this class. + static const type = $DispatcherType(); + static final _id_new0 = _class.constructorId( + r"()V", + ); + + static final _new0 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_NewObject") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public void () + /// The returned object must be released after use, by calling the [release] method. + factory Dispatcher() { + return Dispatcher.fromReference( + _new0(_class.reference.pointer, _id_new0 as jni.JMethodIDPtr) + .reference); + } + + static final _id_getMaxRequests = _class.instanceMethodId( + r"getMaxRequests", + r"()I", + ); + + static final _getMaxRequests = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int getMaxRequests() + int getMaxRequests() { + return _getMaxRequests( + reference.pointer, _id_getMaxRequests as jni.JMethodIDPtr) + .integer; + } + + static final _id_setMaxRequests = _class.instanceMethodId( + r"setMaxRequests", + r"(I)V", + ); + + static final _setMaxRequests = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Int64,)>)>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, jni.JMethodIDPtr, int)>(); + + /// from: public final void setMaxRequests(int i) + void setMaxRequests( + int i, + ) { + _setMaxRequests( + reference.pointer, _id_setMaxRequests as jni.JMethodIDPtr, i) + .check(); + } + + static final _id_getMaxRequestsPerHost = _class.instanceMethodId( + r"getMaxRequestsPerHost", + r"()I", + ); + + static final _getMaxRequestsPerHost = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int getMaxRequestsPerHost() + int getMaxRequestsPerHost() { + return _getMaxRequestsPerHost( + reference.pointer, _id_getMaxRequestsPerHost as jni.JMethodIDPtr) + .integer; + } + + static final _id_setMaxRequestsPerHost = _class.instanceMethodId( + r"setMaxRequestsPerHost", + r"(I)V", + ); + + static final _setMaxRequestsPerHost = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Int64,)>)>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, jni.JMethodIDPtr, int)>(); + + /// from: public final void setMaxRequestsPerHost(int i) + void setMaxRequestsPerHost( + int i, + ) { + _setMaxRequestsPerHost( + reference.pointer, _id_setMaxRequestsPerHost as jni.JMethodIDPtr, i) + .check(); + } + + static final _id_getIdleCallback = _class.instanceMethodId( + r"getIdleCallback", + r"()Ljava/lang/Runnable;", + ); + + static final _getIdleCallback = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final java.lang.Runnable getIdleCallback() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject getIdleCallback() { + return _getIdleCallback( + reference.pointer, _id_getIdleCallback as jni.JMethodIDPtr) + .object(const jni.JObjectType()); + } + + static final _id_setIdleCallback = _class.instanceMethodId( + r"setIdleCallback", + r"(Ljava/lang/Runnable;)V", + ); + + static final _setIdleCallback = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public final void setIdleCallback(java.lang.Runnable runnable) + void setIdleCallback( + jni.JObject runnable, + ) { + _setIdleCallback(reference.pointer, _id_setIdleCallback as jni.JMethodIDPtr, + runnable.reference.pointer) + .check(); + } + + static final _id_executorService = _class.instanceMethodId( + r"executorService", + r"()Ljava/util/concurrent/ExecutorService;", + ); + + static final _executorService = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final java.util.concurrent.ExecutorService executorService() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject executorService() { + return _executorService( + reference.pointer, _id_executorService as jni.JMethodIDPtr) + .object(const jni.JObjectType()); + } + + static final _id_new1 = _class.constructorId( + r"(Ljava/util/concurrent/ExecutorService;)V", + ); + + static final _new1 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_NewObject") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public void (java.util.concurrent.ExecutorService executorService) + /// The returned object must be released after use, by calling the [release] method. + factory Dispatcher.new1( + jni.JObject executorService, + ) { + return Dispatcher.fromReference(_new1(_class.reference.pointer, + _id_new1 as jni.JMethodIDPtr, executorService.reference.pointer) + .reference); + } + + static final _id_cancelAll = _class.instanceMethodId( + r"cancelAll", + r"()V", + ); + + static final _cancelAll = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final void cancelAll() + void cancelAll() { + _cancelAll(reference.pointer, _id_cancelAll as jni.JMethodIDPtr).check(); + } + + static final _id_queuedCalls = _class.instanceMethodId( + r"queuedCalls", + r"()Ljava/util/List;", + ); + + static final _queuedCalls = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final java.util.List queuedCalls() + /// The returned object must be released after use, by calling the [release] method. + jni.JList queuedCalls() { + return _queuedCalls(reference.pointer, _id_queuedCalls as jni.JMethodIDPtr) + .object(const jni.JListType($CallType())); + } + + static final _id_runningCalls = _class.instanceMethodId( + r"runningCalls", + r"()Ljava/util/List;", + ); + + static final _runningCalls = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final java.util.List runningCalls() + /// The returned object must be released after use, by calling the [release] method. + jni.JList runningCalls() { + return _runningCalls( + reference.pointer, _id_runningCalls as jni.JMethodIDPtr) + .object(const jni.JListType($CallType())); + } + + static final _id_queuedCallsCount = _class.instanceMethodId( + r"queuedCallsCount", + r"()I", + ); + + static final _queuedCallsCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int queuedCallsCount() + int queuedCallsCount() { + return _queuedCallsCount( + reference.pointer, _id_queuedCallsCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_runningCallsCount = _class.instanceMethodId( + r"runningCallsCount", + r"()I", + ); + + static final _runningCallsCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int runningCallsCount() + int runningCallsCount() { + return _runningCallsCount( + reference.pointer, _id_runningCallsCount as jni.JMethodIDPtr) + .integer; + } +} + +final class $DispatcherType extends jni.JObjType { + const $DispatcherType(); + + @override + String get signature => r"Lokhttp3/Dispatcher;"; + + @override + Dispatcher fromReference(jni.JReference reference) => + Dispatcher.fromReference(reference); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($DispatcherType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($DispatcherType) && other is $DispatcherType; + } +} From c908f69d168ae394dd0e9eaecf8cff6060b57cc7 Mon Sep 17 00:00:00 2001 From: Anikate-De Date: Tue, 4 Jun 2024 03:24:49 +0530 Subject: [PATCH 2/5] pkgs/ok_http: override the `close()` method from BaseClient --- pkgs/ok_http/lib/src/ok_http_client.dart | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pkgs/ok_http/lib/src/ok_http_client.dart b/pkgs/ok_http/lib/src/ok_http_client.dart index a26f4b518a..8eca7965ea 100644 --- a/pkgs/ok_http/lib/src/ok_http_client.dart +++ b/pkgs/ok_http/lib/src/ok_http_client.dart @@ -44,13 +44,40 @@ import 'jni/bindings.dart' as bindings; /// ``` class OkHttpClient extends BaseClient { late bindings.OkHttpClient _client; + bool _isClosed = false; OkHttpClient() { _client = bindings.OkHttpClient.new1(); } + @override + void close() { + if (!_isClosed) { + // Bindings for `java.util.concurrent.ExecutorService` are erroneous. + // https://github.com/dart-lang/native/issues/588 + // So, use the JClass API to call the `shutdown` method by its signature. + _client + .dispatcher() + .executorService() + .jClass + .instanceMethodId('shutdown', '()V'); + + // Remove all idle connections from the resource pool. + // And, release the JNI reference to the client. + _client + ..connectionPool().evictAll() + ..release(); + } + _isClosed = true; + } + @override Future send(BaseRequest request) async { + if (_isClosed) { + throw ClientException( + 'HTTP request failed. Client is already closed.', request.url); + } + var requestUrl = request.url.toString(); var requestHeaders = request.headers; var requestMethod = request.method; From 3eeee1b94dab23070d16c863076c65e72c20fdd3 Mon Sep 17 00:00:00 2001 From: Anikate-De Date: Tue, 4 Jun 2024 03:25:21 +0530 Subject: [PATCH 3/5] pkgs/ok_http: add `testClose` and `testResponseHeaders` --- pkgs/ok_http/example/integration_test/client_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/ok_http/example/integration_test/client_test.dart b/pkgs/ok_http/example/integration_test/client_test.dart index 2ff9a10399..b888cf6bf4 100644 --- a/pkgs/ok_http/example/integration_test/client_test.dart +++ b/pkgs/ok_http/example/integration_test/client_test.dart @@ -19,9 +19,11 @@ Future testConformance() async { testResponseBody(OkHttpClient(), canStreamResponseBody: false); testRequestHeaders(OkHttpClient()); testRequestMethods(OkHttpClient(), preservesMethodCase: true); + testResponseHeaders(OkHttpClient(), supportsFoldedHeaders: false); testResponseStatusLine(OkHttpClient()); testCompressedResponseBody(OkHttpClient()); testServerErrors(OkHttpClient()); + testClose(OkHttpClient.new); testIsolate(OkHttpClient.new); testResponseCookies(OkHttpClient(), canReceiveSetCookieHeaders: true); }); From a51c3dc2e3b30c93f2fb41e846a2de21a65b14c2 Mon Sep 17 00:00:00 2001 From: Anikate-De Date: Tue, 4 Jun 2024 04:29:36 +0530 Subject: [PATCH 4/5] pkgs/ok_http: add documentation reference to `close()` --- pkgs/ok_http/lib/src/ok_http_client.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/ok_http/lib/src/ok_http_client.dart b/pkgs/ok_http/lib/src/ok_http_client.dart index 8eca7965ea..eae558b5d2 100644 --- a/pkgs/ok_http/lib/src/ok_http_client.dart +++ b/pkgs/ok_http/lib/src/ok_http_client.dart @@ -53,6 +53,9 @@ class OkHttpClient extends BaseClient { @override void close() { if (!_isClosed) { + // Refer to OkHttp documentation for the shutdown procedure: + // https://square.github.io/okhttp/5.x/okhttp/okhttp3/-ok-http-client/index.html#:~:text=Shutdown + // Bindings for `java.util.concurrent.ExecutorService` are erroneous. // https://github.com/dart-lang/native/issues/588 // So, use the JClass API to call the `shutdown` method by its signature. From 9270cc0690cbe46cacd051e5dbf2ff1c6eecbebf Mon Sep 17 00:00:00 2001 From: Anikate-De Date: Tue, 4 Jun 2024 05:01:16 +0530 Subject: [PATCH 5/5] pkgs/ok_http: close cache on `close()` --- pkgs/ok_http/jnigen.yaml | 2 + pkgs/ok_http/lib/src/jni/bindings.dart | 737 ++++++++++++++++++++++- pkgs/ok_http/lib/src/ok_http_client.dart | 12 +- 3 files changed, 744 insertions(+), 7 deletions(-) diff --git a/pkgs/ok_http/jnigen.yaml b/pkgs/ok_http/jnigen.yaml index de56e8937d..1d0d60d457 100644 --- a/pkgs/ok_http/jnigen.yaml +++ b/pkgs/ok_http/jnigen.yaml @@ -25,6 +25,7 @@ classes: - "okhttp3.Callback" - "okhttp3.ConnectionPool" - "okhttp3.Dispatcher" + - "okhttp3.Cache" # Exclude the deprecated methods listed below # They cause syntax errors during the `dart format` step of JNIGen. @@ -79,6 +80,7 @@ exclude: - 'okhttp3.Headers\$Companion#-deprecated_of' - "okhttp3.Headers#-deprecated_size" - "okhttp3.Dispatcher#-deprecated_executorService" + - "okhttp3.Cache#-deprecated_directory" class_path: - "jar/okhttp-4.12.0.jar" diff --git a/pkgs/ok_http/lib/src/jni/bindings.dart b/pkgs/ok_http/lib/src/jni/bindings.dart index 5c17892b3f..53945e6581 100644 --- a/pkgs/ok_http/lib/src/jni/bindings.dart +++ b/pkgs/ok_http/lib/src/jni/bindings.dart @@ -4673,7 +4673,7 @@ class OkHttpClient_Builder extends jni.JObject { /// from: public final okhttp3.OkHttpClient$Builder cache(okhttp3.Cache cache) /// The returned object must be released after use, by calling the [release] method. OkHttpClient_Builder cache( - jni.JObject cache, + Cache cache, ) { return _cache(reference.pointer, _id_cache as jni.JMethodIDPtr, cache.reference.pointer) @@ -5708,9 +5708,9 @@ class OkHttpClient extends jni.JObject { /// from: public final okhttp3.Cache cache() /// The returned object must be released after use, by calling the [release] method. - jni.JObject cache() { + Cache cache() { return _cache(reference.pointer, _id_cache as jni.JMethodIDPtr) - .object(const jni.JObjectType()); + .object(const $CacheType()); } static final _id_dns = _class.instanceMethodId( @@ -8706,3 +8706,734 @@ final class $DispatcherType extends jni.JObjType { return other.runtimeType == ($DispatcherType) && other is $DispatcherType; } } + +/// from: okhttp3.Cache$Companion +class Cache_Companion extends jni.JObject { + @override + late final jni.JObjType $type = type; + + Cache_Companion.fromReference( + jni.JReference reference, + ) : super.fromReference(reference); + + static final _class = jni.JClass.forName(r"okhttp3/Cache$Companion"); + + /// The type which includes information such as the signature of this class. + static const type = $Cache_CompanionType(); + static final _id_key = _class.instanceMethodId( + r"key", + r"(Lokhttp3/HttpUrl;)Ljava/lang/String;", + ); + + static final _key = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public final java.lang.String key(okhttp3.HttpUrl httpUrl) + /// The returned object must be released after use, by calling the [release] method. + jni.JString key( + jni.JObject httpUrl, + ) { + return _key(reference.pointer, _id_key as jni.JMethodIDPtr, + httpUrl.reference.pointer) + .object(const jni.JStringType()); + } + + static final _id_varyMatches = _class.instanceMethodId( + r"varyMatches", + r"(Lokhttp3/Response;Lokhttp3/Headers;Lokhttp3/Request;)Z", + ); + + static final _varyMatches = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs< + ( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer + )>)>>("globalEnv_CallBooleanMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>(); + + /// from: public final boolean varyMatches(okhttp3.Response response, okhttp3.Headers headers, okhttp3.Request request) + bool varyMatches( + Response response, + Headers headers, + Request request, + ) { + return _varyMatches( + reference.pointer, + _id_varyMatches as jni.JMethodIDPtr, + response.reference.pointer, + headers.reference.pointer, + request.reference.pointer) + .boolean; + } + + static final _id_hasVaryAll = _class.instanceMethodId( + r"hasVaryAll", + r"(Lokhttp3/Response;)Z", + ); + + static final _hasVaryAll = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_CallBooleanMethod") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public final boolean hasVaryAll(okhttp3.Response response) + bool hasVaryAll( + Response response, + ) { + return _hasVaryAll(reference.pointer, _id_hasVaryAll as jni.JMethodIDPtr, + response.reference.pointer) + .boolean; + } + + static final _id_varyHeaders = _class.instanceMethodId( + r"varyHeaders", + r"(Lokhttp3/Response;)Lokhttp3/Headers;", + ); + + static final _varyHeaders = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public final okhttp3.Headers varyHeaders(okhttp3.Response response) + /// The returned object must be released after use, by calling the [release] method. + Headers varyHeaders( + Response response, + ) { + return _varyHeaders(reference.pointer, _id_varyHeaders as jni.JMethodIDPtr, + response.reference.pointer) + .object(const $HeadersType()); + } + + static final _id_new0 = _class.constructorId( + r"(Lkotlin/jvm/internal/DefaultConstructorMarker;)V", + ); + + static final _new0 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_NewObject") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public void (kotlin.jvm.internal.DefaultConstructorMarker defaultConstructorMarker) + /// The returned object must be released after use, by calling the [release] method. + factory Cache_Companion( + jni.JObject defaultConstructorMarker, + ) { + return Cache_Companion.fromReference(_new0( + _class.reference.pointer, + _id_new0 as jni.JMethodIDPtr, + defaultConstructorMarker.reference.pointer) + .reference); + } +} + +final class $Cache_CompanionType extends jni.JObjType { + const $Cache_CompanionType(); + + @override + String get signature => r"Lokhttp3/Cache$Companion;"; + + @override + Cache_Companion fromReference(jni.JReference reference) => + Cache_Companion.fromReference(reference); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($Cache_CompanionType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($Cache_CompanionType) && + other is $Cache_CompanionType; + } +} + +/// from: okhttp3.Cache$Entry$Companion +class Cache_Entry_Companion extends jni.JObject { + @override + late final jni.JObjType $type = type; + + Cache_Entry_Companion.fromReference( + jni.JReference reference, + ) : super.fromReference(reference); + + static final _class = jni.JClass.forName(r"okhttp3/Cache$Entry$Companion"); + + /// The type which includes information such as the signature of this class. + static const type = $Cache_Entry_CompanionType(); + static final _id_new0 = _class.constructorId( + r"(Lkotlin/jvm/internal/DefaultConstructorMarker;)V", + ); + + static final _new0 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_NewObject") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: public void (kotlin.jvm.internal.DefaultConstructorMarker defaultConstructorMarker) + /// The returned object must be released after use, by calling the [release] method. + factory Cache_Entry_Companion( + jni.JObject defaultConstructorMarker, + ) { + return Cache_Entry_Companion.fromReference(_new0( + _class.reference.pointer, + _id_new0 as jni.JMethodIDPtr, + defaultConstructorMarker.reference.pointer) + .reference); + } +} + +final class $Cache_Entry_CompanionType + extends jni.JObjType { + const $Cache_Entry_CompanionType(); + + @override + String get signature => r"Lokhttp3/Cache$Entry$Companion;"; + + @override + Cache_Entry_Companion fromReference(jni.JReference reference) => + Cache_Entry_Companion.fromReference(reference); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($Cache_Entry_CompanionType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($Cache_Entry_CompanionType) && + other is $Cache_Entry_CompanionType; + } +} + +/// from: okhttp3.Cache +class Cache extends jni.JObject { + @override + late final jni.JObjType $type = type; + + Cache.fromReference( + jni.JReference reference, + ) : super.fromReference(reference); + + static final _class = jni.JClass.forName(r"okhttp3/Cache"); + + /// The type which includes information such as the signature of this class. + static const type = $CacheType(); + static final _id_Companion = _class.staticFieldId( + r"Companion", + r"Lokhttp3/Cache$Companion;", + ); + + /// from: static public final okhttp3.Cache$Companion Companion + /// The returned object must be released after use, by calling the [release] method. + static Cache_Companion get Companion => + _id_Companion.get(_class, const $Cache_CompanionType()); + + static final _id_new0 = _class.constructorId( + r"(Ljava/io/File;JLokhttp3/internal/io/FileSystem;)V", + ); + + static final _new0 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs< + ( + ffi.Pointer, + ffi.Int64, + ffi.Pointer + )>)>>("globalEnv_NewObject") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer, int, ffi.Pointer)>(); + + /// from: public void (java.io.File file, long j, okhttp3.internal.io.FileSystem fileSystem) + /// The returned object must be released after use, by calling the [release] method. + factory Cache( + jni.JObject file, + int j, + jni.JObject fileSystem, + ) { + return Cache.fromReference(_new0( + _class.reference.pointer, + _id_new0 as jni.JMethodIDPtr, + file.reference.pointer, + j, + fileSystem.reference.pointer) + .reference); + } + + static final _id_isClosed = _class.instanceMethodId( + r"isClosed", + r"()Z", + ); + + static final _isClosed = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallBooleanMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final boolean isClosed() + bool isClosed() { + return _isClosed(reference.pointer, _id_isClosed as jni.JMethodIDPtr) + .boolean; + } + + static final _id_new1 = _class.constructorId( + r"(Ljava/io/File;J)V", + ); + + static final _new1 = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer, ffi.Int64)>)>>( + "globalEnv_NewObject") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer, int)>(); + + /// from: public void (java.io.File file, long j) + /// The returned object must be released after use, by calling the [release] method. + factory Cache.new1( + jni.JObject file, + int j, + ) { + return Cache.fromReference(_new1(_class.reference.pointer, + _id_new1 as jni.JMethodIDPtr, file.reference.pointer, j) + .reference); + } + + static final _id_initialize = _class.instanceMethodId( + r"initialize", + r"()V", + ); + + static final _initialize = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final void initialize() + void initialize() { + _initialize(reference.pointer, _id_initialize as jni.JMethodIDPtr).check(); + } + + static final _id_delete = _class.instanceMethodId( + r"delete", + r"()V", + ); + + static final _delete = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final void delete() + void delete() { + _delete(reference.pointer, _id_delete as jni.JMethodIDPtr).check(); + } + + static final _id_evictAll = _class.instanceMethodId( + r"evictAll", + r"()V", + ); + + static final _evictAll = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final void evictAll() + void evictAll() { + _evictAll(reference.pointer, _id_evictAll as jni.JMethodIDPtr).check(); + } + + static final _id_urls = _class.instanceMethodId( + r"urls", + r"()Ljava/util/Iterator;", + ); + + static final _urls = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final java.util.Iterator urls() + /// The returned object must be released after use, by calling the [release] method. + jni.JIterator urls() { + return _urls(reference.pointer, _id_urls as jni.JMethodIDPtr) + .object(const jni.JIteratorType(jni.JStringType())); + } + + static final _id_writeAbortCount = _class.instanceMethodId( + r"writeAbortCount", + r"()I", + ); + + static final _writeAbortCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int writeAbortCount() + int writeAbortCount() { + return _writeAbortCount( + reference.pointer, _id_writeAbortCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_writeSuccessCount = _class.instanceMethodId( + r"writeSuccessCount", + r"()I", + ); + + static final _writeSuccessCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int writeSuccessCount() + int writeSuccessCount() { + return _writeSuccessCount( + reference.pointer, _id_writeSuccessCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_size = _class.instanceMethodId( + r"size", + r"()J", + ); + + static final _size = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallLongMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final long size() + int size() { + return _size(reference.pointer, _id_size as jni.JMethodIDPtr).long; + } + + static final _id_maxSize = _class.instanceMethodId( + r"maxSize", + r"()J", + ); + + static final _maxSize = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallLongMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final long maxSize() + int maxSize() { + return _maxSize(reference.pointer, _id_maxSize as jni.JMethodIDPtr).long; + } + + static final _id_flush = _class.instanceMethodId( + r"flush", + r"()V", + ); + + static final _flush = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public void flush() + void flush() { + _flush(reference.pointer, _id_flush as jni.JMethodIDPtr).check(); + } + + static final _id_close = _class.instanceMethodId( + r"close", + r"()V", + ); + + static final _close = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallVoidMethod") + .asFunction< + jni.JThrowablePtr Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public void close() + void close() { + _close(reference.pointer, _id_close as jni.JMethodIDPtr).check(); + } + + static final _id_directory = _class.instanceMethodId( + r"directory", + r"()Ljava/io/File;", + ); + + static final _directory = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallObjectMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final java.io.File directory() + /// The returned object must be released after use, by calling the [release] method. + jni.JObject directory() { + return _directory(reference.pointer, _id_directory as jni.JMethodIDPtr) + .object(const jni.JObjectType()); + } + + static final _id_networkCount = _class.instanceMethodId( + r"networkCount", + r"()I", + ); + + static final _networkCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int networkCount() + int networkCount() { + return _networkCount( + reference.pointer, _id_networkCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_hitCount = _class.instanceMethodId( + r"hitCount", + r"()I", + ); + + static final _hitCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int hitCount() + int hitCount() { + return _hitCount(reference.pointer, _id_hitCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_requestCount = _class.instanceMethodId( + r"requestCount", + r"()I", + ); + + static final _requestCount = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>>("globalEnv_CallIntMethod") + .asFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + )>(); + + /// from: public final int requestCount() + int requestCount() { + return _requestCount( + reference.pointer, _id_requestCount as jni.JMethodIDPtr) + .integer; + } + + static final _id_key = _class.staticMethodId( + r"key", + r"(Lokhttp3/HttpUrl;)Ljava/lang/String;", + ); + + static final _key = ProtectedJniExtensions.lookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + jni.JMethodIDPtr, + ffi.VarArgs<(ffi.Pointer,)>)>>( + "globalEnv_CallStaticObjectMethod") + .asFunction< + jni.JniResult Function(ffi.Pointer, jni.JMethodIDPtr, + ffi.Pointer)>(); + + /// from: static public final java.lang.String key(okhttp3.HttpUrl httpUrl) + /// The returned object must be released after use, by calling the [release] method. + static jni.JString key( + jni.JObject httpUrl, + ) { + return _key(_class.reference.pointer, _id_key as jni.JMethodIDPtr, + httpUrl.reference.pointer) + .object(const jni.JStringType()); + } +} + +final class $CacheType extends jni.JObjType { + const $CacheType(); + + @override + String get signature => r"Lokhttp3/Cache;"; + + @override + Cache fromReference(jni.JReference reference) => + Cache.fromReference(reference); + + @override + jni.JObjType get superType => const jni.JObjectType(); + + @override + final superCount = 1; + + @override + int get hashCode => ($CacheType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == ($CacheType) && other is $CacheType; + } +} diff --git a/pkgs/ok_http/lib/src/ok_http_client.dart b/pkgs/ok_http/lib/src/ok_http_client.dart index eae558b5d2..c2d19b90b7 100644 --- a/pkgs/ok_http/lib/src/ok_http_client.dart +++ b/pkgs/ok_http/lib/src/ok_http_client.dart @@ -66,10 +66,14 @@ class OkHttpClient extends BaseClient { .instanceMethodId('shutdown', '()V'); // Remove all idle connections from the resource pool. - // And, release the JNI reference to the client. - _client - ..connectionPool().evictAll() - ..release(); + _client.connectionPool().evictAll(); + + // Close the cache and release the JNI reference to the client. + var cache = _client.cache(); + if (!cache.isNull) { + cache.close(); + } + _client.release(); } _isClosed = true; }