From f4b5d7aee43dbaa4c227c2ddea86bb79929e50f6 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Wed, 1 Mar 2023 15:05:38 +0100 Subject: [PATCH] Use a common class Wrapper and IterWrapper to wrapp native resource. Native resource (pointer to shared_ptr) is stored as a long in the `Wrapper.Resource` class. As Wrapper implements AutoCloseable and we register the (java) resource to be cleaned at object destruction, we now properly delete the native resource. This also adding new macro to avoid writting the class name and so reduce potential typos. # Conflicts: # lib/build.gradle # lib/src/main/java/org/kiwix/libkiwix/Library.java --- lib/build.gradle | 6 +- lib/src/main/cpp/CMakeLists.txt | 2 + lib/src/main/cpp/libkiwix/book.cpp | 10 +- lib/src/main/cpp/libkiwix/bookmark.cpp | 8 +- lib/src/main/cpp/libkiwix/filter.cpp | 8 +- lib/src/main/cpp/libkiwix/kiwixserver.cpp | 13 +- lib/src/main/cpp/libkiwix/library.cpp | 11 +- lib/src/main/cpp/libkiwix/manager.cpp | 6 +- lib/src/main/cpp/libzim/archive.cpp | 118 +++--- lib/src/main/cpp/libzim/blob.cpp | 2 - lib/src/main/cpp/libzim/entry.cpp | 9 +- lib/src/main/cpp/libzim/entry_iterator.cpp | 50 +-- lib/src/main/cpp/libzim/item.cpp | 7 +- lib/src/main/cpp/libzim/query.cpp | 13 +- lib/src/main/cpp/libzim/search.cpp | 13 +- lib/src/main/cpp/libzim/search_iterator.cpp | 12 +- lib/src/main/cpp/libzim/searcher.cpp | 26 +- lib/src/main/cpp/libzim/suggestion_item.cpp | 2 - .../main/cpp/libzim/suggestion_iterator.cpp | 12 +- lib/src/main/cpp/libzim/suggestion_search.cpp | 13 +- .../main/cpp/libzim/suggestion_searcher.cpp | 16 +- lib/src/main/cpp/macros.h | 2 - lib/src/main/cpp/utils.h | 360 +++++++++++++++++- lib/src/main/cpp/wrapper.cpp | 55 +++ lib/src/main/java/org/kiwix/IterWrapper.java | 46 +++ lib/src/main/java/org/kiwix/Wrapper.java | 40 ++ .../main/java/org/kiwix/libkiwix/Book.java | 14 +- .../java/org/kiwix/libkiwix/Bookmark.java | 17 +- .../main/java/org/kiwix/libkiwix/Filter.java | 16 +- .../java/org/kiwix/libkiwix/Illustration.java | 9 +- .../main/java/org/kiwix/libkiwix/Library.java | 11 +- .../main/java/org/kiwix/libkiwix/Manager.java | 11 +- .../main/java/org/kiwix/libkiwix/Server.java | 13 +- .../main/java/org/kiwix/libzim/Archive.java | 35 +- lib/src/main/java/org/kiwix/libzim/Blob.java | 18 +- lib/src/main/java/org/kiwix/libzim/Entry.java | 16 +- .../java/org/kiwix/libzim/EntryIterator.java | 20 +- lib/src/main/java/org/kiwix/libzim/Item.java | 16 +- lib/src/main/java/org/kiwix/libzim/Query.java | 19 +- .../main/java/org/kiwix/libzim/Search.java | 17 +- .../java/org/kiwix/libzim/SearchIterator.java | 14 - .../main/java/org/kiwix/libzim/Searcher.java | 28 +- .../java/org/kiwix/libzim/SuggestionItem.java | 13 +- .../org/kiwix/libzim/SuggestionIterator.java | 17 +- .../org/kiwix/libzim/SuggestionSearch.java | 14 +- .../org/kiwix/libzim/SuggestionSearcher.java | 21 +- 46 files changed, 694 insertions(+), 505 deletions(-) create mode 100644 lib/src/main/cpp/wrapper.cpp create mode 100644 lib/src/main/java/org/kiwix/IterWrapper.java create mode 100644 lib/src/main/java/org/kiwix/Wrapper.java diff --git a/lib/build.gradle b/lib/build.gradle index f4b5115..7d3ae13 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -26,11 +26,11 @@ ext { apply from: 'publish.gradle' android { - compileSdk 32 + compileSdk 33 defaultConfig { - minSdk 21 + minSdk 33 targetSdk 32 versionCode 1 versionName "1.0" @@ -285,7 +285,7 @@ task checkCurrentJavaVersion() { task generateHeaderFilesFromJavaWrapper(type: Exec) { workingDir "${projectDir}/src/main/java/org/kiwix/" - commandLine 'bash', '-c', "javac -h ${buildDir}/include/javah_generated/ -d ${buildDir}/libzim/ ${getLibzimFiles()} ${getLibkiwixFiles()}" + commandLine 'bash', '-c', "javac -h ${buildDir}/include/javah_generated/ -d ${buildDir}/libzim/ *.java ${getLibzimFiles()} ${getLibkiwixFiles()}" } String getLibkiwixFiles() { diff --git a/lib/src/main/cpp/CMakeLists.txt b/lib/src/main/cpp/CMakeLists.txt index f768ff2..977eba0 100644 --- a/lib/src/main/cpp/CMakeLists.txt +++ b/lib/src/main/cpp/CMakeLists.txt @@ -10,6 +10,7 @@ add_library( zim_wrapper SHARED + wrapper.cpp libzim/archive.cpp libzim/entry.cpp libzim/entry_iterator.cpp @@ -45,6 +46,7 @@ add_library( kiwix_wrapper SHARED + wrapper.cpp libkiwix/book.cpp libkiwix/filter.cpp libkiwix/kiwixicu.cpp diff --git a/lib/src/main/cpp/libkiwix/book.cpp b/lib/src/main/cpp/libkiwix/book.cpp index 81ec03b..9470eb4 100644 --- a/lib/src/main/cpp/libkiwix/book.cpp +++ b/lib/src/main/cpp/libkiwix/book.cpp @@ -29,13 +29,11 @@ #define TYPENAME libkiwix_Book #include -METHOD0(void, allocate) +METHOD0(jobject, getNativeBook) { - SET_PTR(std::make_shared()); + return NEW_RESOURCE(std::make_shared()); } -DISPOSE - METHOD(void, update__Lorg_kiwix_libkiwix_Book_2, jobject otherBook) { THIS->update(*getPtr(env, otherBook)); @@ -93,12 +91,12 @@ METHOD0(jobjectArray, getIllustrations) { jobjectArray retArray = createArray(env, illustrations.size(), "org/kiwix/libkiwix/Illustration"); size_t index = 0; for (auto illu: illustrations) { - auto wrapper = BUILD_WRAPPER("org/kiwix/libkiwx/Illustration", illu); + auto wrapper = BUILD_WRAPPER(illu); env->SetObjectArrayElement(retArray, index++, wrapper); } return retArray; } METHOD(jobject, getIllustration, jint size) { - return BUILD_WRAPPER("org/kiwix/libkiwix/Illustration", THIS->getIllustration(TO_C(size))); + return BUILD_WRAPPER(THIS->getIllustration(TO_C(size))); } diff --git a/lib/src/main/cpp/libkiwix/bookmark.cpp b/lib/src/main/cpp/libkiwix/bookmark.cpp index f14300c..ae14f6a 100644 --- a/lib/src/main/cpp/libkiwix/bookmark.cpp +++ b/lib/src/main/cpp/libkiwix/bookmark.cpp @@ -26,15 +26,13 @@ #define NATIVE_TYPE kiwix::Bookmark #define TYPENAME libkiwix_Bookmark -#include +#include "macros.h" -METHOD0(void, setNativeBookmark) +METHOD0(jobject, buildNativeBookmark) { - SET_PTR(std::make_shared()); + return NEW_RESOURCE(std::make_shared()); } -DISPOSE - GETTER(jstring, getBookId) GETTER(jstring, getBookTitle) diff --git a/lib/src/main/cpp/libkiwix/filter.cpp b/lib/src/main/cpp/libkiwix/filter.cpp index 4e4a5f3..294059d 100644 --- a/lib/src/main/cpp/libkiwix/filter.cpp +++ b/lib/src/main/cpp/libkiwix/filter.cpp @@ -28,15 +28,11 @@ #define TYPENAME libkiwix_Filter #include "macros.h" - - /* Kiwix Reader JNI functions */ -METHOD0(void, allocate) { - SET_PTR(std::make_shared()); +METHOD0(jobject, getNativeFilter) { + return NEW_RESOURCE(std::make_shared()); } -DISPOSE - #define FORWARD(name, args_type) \ METHOD(jobject, name, args_type value) { \ THIS->name(jni2c(value, env)); \ diff --git a/lib/src/main/cpp/libkiwix/kiwixserver.cpp b/lib/src/main/cpp/libkiwix/kiwixserver.cpp index 289e203..cd626c4 100644 --- a/lib/src/main/cpp/libkiwix/kiwixserver.cpp +++ b/lib/src/main/cpp/libkiwix/kiwixserver.cpp @@ -32,21 +32,14 @@ /* Kiwix Reader JNI functions */ -METHOD(void, setNativeServer, jobject jLibrary) +METHOD(jobject, buildNativeServer, jobject jLibrary) { LOG("Attempting to create server"); - try { - auto library = getPtr(env, jLibrary); - SET_PTR(std::make_shared(library.get())); - } catch (std::exception& e) { - LOG("Error creating the server"); - LOG("%s", e.what()); - } + auto library = getPtr(env, jLibrary); + return NEW_RESOURCE(std::make_shared(library.get())); } -DISPOSE - /* Kiwix library functions */ METHOD(void, setRoot, jstring root) { diff --git a/lib/src/main/cpp/libkiwix/library.cpp b/lib/src/main/cpp/libkiwix/library.cpp index e27e60d..9c4bdb9 100644 --- a/lib/src/main/cpp/libkiwix/library.cpp +++ b/lib/src/main/cpp/libkiwix/library.cpp @@ -29,12 +29,11 @@ #include "macros.h" /* Kiwix Reader JNI functions */ -METHOD0(void, setNativeHandler) +METHOD0(jobject, buildNativeLibrary) { - SET_PTR(std::make_shared()); + return NEW_RESOURCE(std::make_shared()); } -DISPOSE /* Kiwix library functions */ METHOD(jboolean, addBook, jobject book) @@ -50,11 +49,11 @@ METHOD(jboolean, addBook, jobject book) } METHOD(jobject, getBookById, jstring id) { - return BUILD_WRAPPER("org/kiwix/libkiwix/Book", THIS->getBookById(TO_C(id))); + return BUILD_WRAPPER(THIS->getBookById(TO_C(id))); } METHOD(jobject, getArchiveById, jstring id) { - return BUILD_WRAPPER("org/kiwix/libzim/Archive", THIS->getArchiveById(TO_C(id))); + return BUILD_WRAPPER(THIS->getArchiveById(TO_C(id))); } METHOD(jboolean, removeBookById, jstring id) { @@ -98,7 +97,7 @@ METHOD(jobjectArray, getBookmarks, jboolean onlyValidBookmarks) { jobjectArray retArray = createArray(env, bookmarks.size(), "org/kiwix/libkiwix/Bookmark"); size_t index = 0; for (auto bookmark: bookmarks) { - auto wrapper = BUILD_WRAPPER("org/kiwix/libkiwx/Bookmark", bookmark); + auto wrapper = BUILD_WRAPPER(bookmark); env->SetObjectArrayElement(retArray, index++, wrapper); } return retArray; diff --git a/lib/src/main/cpp/libkiwix/manager.cpp b/lib/src/main/cpp/libkiwix/manager.cpp index cc9a9bd..e0d36fe 100644 --- a/lib/src/main/cpp/libkiwix/manager.cpp +++ b/lib/src/main/cpp/libkiwix/manager.cpp @@ -28,14 +28,12 @@ #define TYPENAME libkiwix_Manager #include -METHOD(void, allocate, jobject libraryObj) +METHOD(jobject, buildNativeManager, jobject libraryObj) { auto lib = getPtr(env, libraryObj); - SET_PTR(std::make_shared(lib.get())); + return NEW_RESOURCE(std::make_shared(lib.get())); } -DISPOSE - /* Kiwix manager functions */ METHOD(jboolean, readFile, jstring path) { diff --git a/lib/src/main/cpp/libzim/archive.cpp b/lib/src/main/cpp/libzim/archive.cpp index 3392977..2545cf0 100644 --- a/lib/src/main/cpp/libzim/archive.cpp +++ b/lib/src/main/cpp/libzim/archive.cpp @@ -36,18 +36,13 @@ #include /* Kiwix Reader JNI functions */ -METHOD(void, setNativeArchive, jstring filename) +METHOD(jobject, buildNativeArchive, jstring filename) { std::string cPath = TO_C(filename); LOG("Attempting to create reader with: %s", cPath.c_str()); - try { - auto archive = std::make_shared(cPath); - SET_PTR(archive); - } catch (std::exception& e) { - LOG("Error opening ZIM file"); - LOG("%s", e.what()); - } + auto archive = std::make_shared(cPath); + return NEW_RESOURCE(archive); } namespace @@ -70,7 +65,7 @@ int jni2fd(const jobject& fdObj, JNIEnv* env) } // unnamed namespace -JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveByFD( +JNIEXPORT jobject JNICALL Java_org_kiwix_libzim_Archive_buildNativeArchiveByFD( JNIEnv* env, jobject thisObj, jobject fdObj) { #ifndef _WIN32 @@ -79,18 +74,16 @@ JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveByFD( LOG("Attempting to create reader with fd: %d", fd); try { auto archive = std::make_shared(fd); - SET_PTR(archive); - } catch (std::exception& e) { - LOG("Error opening ZIM file"); - LOG("%s", e.what()); - } + return NEW_RESOURCE(archive); + } CATCH("Error opening ZIM file") #else jclass exception = env->FindClass("java/lang/UnsupportedOperationException"); env->ThrowNew(exception, "org.kiwix.libzim.Archive.setNativeArchiveByFD() is not supported under Windows"); #endif + return nullptr; } -JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveEmbedded( +JNIEXPORT jobject JNICALL Java_org_kiwix_libzim_Archive_buildNativeArchiveEmbedded( JNIEnv* env, jobject thisObj, jobject fdObj, jlong offset, jlong size) { #ifndef _WIN32 @@ -99,19 +92,15 @@ JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveEmbedded( LOG("Attempting to create reader with fd: %d", fd); try { auto archive = std::make_shared(fd, offset, size); - SET_PTR(archive); - } catch (std::exception& e) { - LOG("Error opening ZIM file"); - LOG("%s", e.what()); - } + return NEW_RESOURCE(archive); + } CATCH("Error opening ZIM file") #else jclass exception = env->FindClass("java/lang/UnsupportedOperationException"); env->ThrowNew(exception, "org.kiwix.libzim.Archive.setNativeArchiveEmbedded() is not supported under Windows"); #endif + return nullptr; } -DISPOSE - GETTER(jstring, getFilename) GETTER(jlong, getFilesize) GETTER(jint, getAllEntryCount) @@ -128,13 +117,13 @@ METHOD(jstring, getMetadata, jstring name) { } METHOD(jobject, getMetadataItem, jstring name) { - return BUILD_WRAPPER("org/kiwix/libzim/Item", THIS->getMetadataItem(TO_C(name))); + return BUILD_WRAPPER(THIS->getMetadataItem(TO_C(name))); } GETTER(jobjectArray, getMetadataKeys) METHOD(jobject, getIllustrationItem, jint size) { - return BUILD_WRAPPER("org/kiwix/libzim/Item", THIS->getIllustrationItem(TO_C(size))); + return BUILD_WRAPPER(THIS->getIllustrationItem(TO_C(size))); } METHOD(jboolean, hasIllustration, jint size) { @@ -144,11 +133,11 @@ METHOD(jboolean, hasIllustration, jint size) { GETTER(jlongArray, getIllustrationSizes) METHOD(jobject, getEntryByPath__Ljava_lang_String_2, jstring path) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getEntryByPath(TO_C(path))); + return BUILD_WRAPPER(THIS->getEntryByPath(TO_C(path))); } METHOD(jobject, getEntryByPath__I, jint index) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getEntryByPath(TO_C(index))); + return BUILD_WRAPPER(THIS->getEntryByPath(TO_C(index))); } METHOD(jboolean, hasEntryByPath, jstring path) { @@ -156,11 +145,11 @@ METHOD(jboolean, hasEntryByPath, jstring path) { } METHOD(jobject, getEntryByTitle__Ljava_lang_String_2, jstring title) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getEntryByTitle(TO_C(title))); + return BUILD_WRAPPER(THIS->getEntryByTitle(TO_C(title))); } METHOD(jobject, getEntryByTitle__I, jint index) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getEntryByTitle(TO_C(index))); + return BUILD_WRAPPER(THIS->getEntryByTitle(TO_C(index))); } METHOD(jboolean, hasEntryByTitle, jstring title) { @@ -168,17 +157,17 @@ METHOD(jboolean, hasEntryByTitle, jstring title) { } METHOD(jobject, getEntryByClusterOrder, jint index) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getEntryByClusterOrder(TO_C(index))); + return BUILD_WRAPPER(THIS->getEntryByClusterOrder(TO_C(index))); } METHOD0(jobject, getMainEntry) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getMainEntry()); + return BUILD_WRAPPER(THIS->getMainEntry()); } GETTER(jboolean, hasMainEntry) METHOD0(jobject, getRandomEntry) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getRandomEntry()); + return BUILD_WRAPPER(THIS->getRandomEntry()); } GETTER(jboolean, hasFulltextIndex) @@ -192,62 +181,57 @@ GETTER(jboolean, hasNewNamespaceScheme) #define ITER_BY_PATH 0 #define ITER_BY_TITLE 1 #define ITER_EFFICIENT 2 + + +// No use of the macro BUILD_WRAPPER as `EntryIterator` takes a integer(I) to +// track the order. So the signature of the constructor is not the same. +// The same way, as we are building a iterator, it has two nativeHandle (for begin and end). METHOD0(jobject, iterByPath) { auto range = THIS->iterByPath(); - jclass objClass = env->FindClass("org/kiwix/libzim/EntryIterator"); - jmethodID initMethod = env->GetMethodID(objClass, "", "(I)V"); - jobject obj = env->NewObject(objClass, initMethod, ITER_BY_PATH); - SET_HANDLE(zim::Archive::iterator, obj, range.begin()); + auto beginIter = NEW_RESOURCE(range.begin()); + auto endIter = NEW_RESOURCE(range.end()); - auto end_ptr = std::make_shared>(range.end()); - setPtr(env, obj, std::move(end_ptr), "nativeHandleEnd"); - return obj; + jclass wrapperClass = env->FindClass("org/kiwix/libzim/EntryIterator"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource;org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, beginIter, endIter); } METHOD0(jobject, iterByTitle) { auto range = THIS->iterByTitle(); - jclass objClass = env->FindClass("org/kiwix/libzim/EntryIterator"); - jmethodID initMethod = env->GetMethodID(objClass, "", "(I)V"); - jobject obj = env->NewObject(objClass, initMethod, ITER_BY_TITLE); - SET_HANDLE(zim::Archive::iterator, obj, range.begin()); + auto beginIter = NEW_RESOURCE(range.begin()); + auto endIter = NEW_RESOURCE(range.end()); - auto end_ptr = std::make_shared>(range.end()); - setPtr(env, obj, std::move(end_ptr), "nativeHandleEnd"); - return obj; + jclass wrapperClass = env->FindClass("org/kiwix/libzim/EntryIterator"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource;org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, beginIter, endIter); } METHOD0(jobject, iterEfficient) { auto range = THIS->iterEfficient(); - jclass objClass = env->FindClass("org/kiwix/libzim/EntryIterator"); - jmethodID initMethod = env->GetMethodID(objClass, "", "(I)V"); - jobject obj = env->NewObject(objClass, initMethod, ITER_EFFICIENT); - SET_HANDLE(zim::Archive::iterator, obj, range.begin()); + auto beginIter = NEW_RESOURCE(range.begin()); + auto endIter = NEW_RESOURCE(range.end()); - auto end_ptr = std::make_shared>(range.end()); - setPtr(env, obj, std::move(end_ptr), "nativeHandleEnd"); - return obj; + jclass wrapperClass = env->FindClass("org/kiwix/libzim/EntryIterator"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource;org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, beginIter, endIter); } METHOD(jobject, findByPath, jstring path) { auto range = THIS->findByPath(TO_C(path)); - jclass objClass = env->FindClass("org/kiwix/libzim/EntryIterator"); - jmethodID initMethod = env->GetMethodID(objClass, "", "(I)V"); - jobject obj = env->NewObject(objClass, initMethod, ITER_BY_PATH); - SET_HANDLE(zim::Archive::iterator, obj, range.begin()); + auto beginIter = NEW_RESOURCE(range.begin()); + auto endIter = NEW_RESOURCE(range.end()); - auto end_ptr = std::make_shared>(range.end()); - setPtr(env, obj, std::move(end_ptr), "nativeHandleEnd"); - return obj; + jclass wrapperClass = env->FindClass("org/kiwix/libzim/EntryIterator"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource;org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, beginIter, endIter); } METHOD(jobject, findByTitle, jstring title) { auto range = THIS->findByTitle(TO_C(title)); - jclass objClass = env->FindClass("org/kiwix/libzim/EntryIterator"); - jmethodID initMethod = env->GetMethodID(objClass, "", "(I)V"); - jobject obj = env->NewObject(objClass, initMethod, ITER_BY_TITLE); - SET_HANDLE(zim::Archive::iterator, obj, range.begin()); - - auto end_ptr = std::make_shared>(range.end()); - setPtr(env, obj, std::move(end_ptr), "nativeHandleEnd"); - return obj; + auto beginIter = NEW_RESOURCE(range.begin()); + auto endIter = NEW_RESOURCE(range.end()); + + jclass wrapperClass = env->FindClass("org/kiwix/libzim/EntryIterator"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource;org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, beginIter, endIter); } diff --git a/lib/src/main/cpp/libzim/blob.cpp b/lib/src/main/cpp/libzim/blob.cpp index a197e11..4eee23d 100644 --- a/lib/src/main/cpp/libzim/blob.cpp +++ b/lib/src/main/cpp/libzim/blob.cpp @@ -33,8 +33,6 @@ #define TYPENAME libzim_Blob #include -DISPOSE - METHOD0(jstring, getData) { return TO_JNI(std::string(*THIS)); } diff --git a/lib/src/main/cpp/libzim/entry.cpp b/lib/src/main/cpp/libzim/entry.cpp index 2652e25..56022e3 100644 --- a/lib/src/main/cpp/libzim/entry.cpp +++ b/lib/src/main/cpp/libzim/entry.cpp @@ -34,20 +34,17 @@ #define TYPENAME libzim_Entry #include - -DISPOSE - GETTER(jboolean, isRedirect) GETTER(jstring, getTitle) GETTER(jstring, getPath) METHOD(jobject, getItem, jboolean follow) { - return BUILD_WRAPPER("org/kiwix/libzim/Item", THIS->getItem(TO_C(follow))); + return BUILD_WRAPPER(THIS->getItem(TO_C(follow))); } METHOD0(jobject, getRedirect) { - return BUILD_WRAPPER("org/kiwix/libzim/Item", THIS->getRedirect()); + return BUILD_WRAPPER(THIS->getRedirect()); } METHOD0(jobject, getRedirectEntry) { - return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getRedirectEntry()); + return BUILD_WRAPPER(THIS->getRedirectEntry()); } diff --git a/lib/src/main/cpp/libzim/entry_iterator.cpp b/lib/src/main/cpp/libzim/entry_iterator.cpp index 9f19d56..72fcc9f 100644 --- a/lib/src/main/cpp/libzim/entry_iterator.cpp +++ b/lib/src/main/cpp/libzim/entry_iterator.cpp @@ -43,44 +43,24 @@ inline int get_order(JNIEnv* env, jobject thisObj) { return TO_C(env->GetIntField(thisObj, fieldId)); } -METHOD0(void, dispose) -{ - // Delete end iterator - switch (get_order(env, thisObj)) { - case 0: - dispose(env, thisObj, "nativeHandleEnd"); - dispose(env, thisObj); - break; - case 1: - dispose(env, thisObj, "nativeHandleEnd"); - dispose(env, thisObj); - break; - case 2: - dispose(env, thisObj, "nativeHandleEnd"); - dispose(env, thisObj); - break; - } -} - - METHOD0(jboolean, hasNext) { switch (get_order(env, thisObj)) { case 0: { - PATH_NATIVE_TYPE next(*GET_PTR(PATH_NATIVE_TYPE)); + PATH_NATIVE_TYPE next(*getPtr(env, thisObj, "nativeResourceBegin")); next++; - auto end = getPtr(env, thisObj, "nativeHandleEnd"); + auto end = getPtr(env, thisObj, "nativeResourceEnd"); return next == *end; } case 1: { - TITLE_NATIVE_TYPE next(*GET_PTR(TITLE_NATIVE_TYPE)); + TITLE_NATIVE_TYPE next(*getPtr(env, thisObj, "nativeResourceBegin")); next++; - auto end = getPtr(env, thisObj, "nativeHandleEnd"); + auto end = getPtr(env, thisObj, "nativeResourceEnd"); return next == *end; } case 2: { - EFFICIENT_NATIVE_TYPE next(*GET_PTR(EFFICIENT_NATIVE_TYPE)); + EFFICIENT_NATIVE_TYPE next(*getPtr(env, thisObj, "nativeResourceBegin")); next++; - auto end = getPtr(env, thisObj, "nativeHandleEnd"); + auto end = getPtr(env, thisObj, "nativeResourceEnd"); return next == *end; } default: @@ -92,19 +72,19 @@ METHOD0(jboolean, hasNext) { METHOD0(jobject, next) { switch (get_order(env, thisObj)) { case 0: { - (*GET_PTR(PATH_NATIVE_TYPE))++; - zim::Entry entry = **GET_PTR(PATH_NATIVE_TYPE); - return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); + (*getPtr(env, thisObj, "nativeResourceBegin"))++; + zim::Entry entry = **getPtr(env, thisObj, "nativeResourceBegin"); + return BUILD_WRAPPER(entry); } case 1: { - (*GET_PTR(TITLE_NATIVE_TYPE))++; - zim::Entry entry = **GET_PTR(TITLE_NATIVE_TYPE); - return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); + (*getPtr(env, thisObj, "nativeResourceBegin"))++; + zim::Entry entry = **getPtr(env, thisObj, "nativeResourceBegin"); + return BUILD_WRAPPER(entry); } case 2: { - (*GET_PTR(EFFICIENT_NATIVE_TYPE))++; - zim::Entry entry = **GET_PTR(EFFICIENT_NATIVE_TYPE); - return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); + (*getPtr(env, thisObj, "nativeResourceBegin"))++; + zim::Entry entry = **getPtr(env, thisObj, "nativeResourceBegin"); + return BUILD_WRAPPER(entry); } default: // unreachable!() diff --git a/lib/src/main/cpp/libzim/item.cpp b/lib/src/main/cpp/libzim/item.cpp index 500797f..c8da5d1 100644 --- a/lib/src/main/cpp/libzim/item.cpp +++ b/lib/src/main/cpp/libzim/item.cpp @@ -33,21 +33,20 @@ #define TYPENAME libzim_Item #include -DISPOSE - GETTER(jstring, getTitle) GETTER(jstring, getPath) GETTER(jstring, getMimetype) METHOD0(jobject, getData) { - return BUILD_WRAPPER("org/kiwix/libzim/Blob", THIS->getData()); + return BUILD_WRAPPER(THIS->getData()); } GETTER(jlong, getSize) METHOD0(jobject, getDirectAccessInformation) { - jobject directObjInfo = newObject("org/kiwix/libzim/DirectAccessInfo", env); + //return BUILD_WRAPPER(THIS->getDirectAccessInformation()); + jobject directObjInfo = NEW_OBJECT("org/kiwix/libzim/DirectAccessInfo"); setDaiObjValue("", 0, directObjInfo, env); auto cDirectObjInfo = THIS->getDirectAccessInformation(); diff --git a/lib/src/main/cpp/libzim/query.cpp b/lib/src/main/cpp/libzim/query.cpp index 6117b4d..2804772 100644 --- a/lib/src/main/cpp/libzim/query.cpp +++ b/lib/src/main/cpp/libzim/query.cpp @@ -33,20 +33,11 @@ #define TYPENAME libzim_Query #include -METHOD(void, setNativeQuery, jstring query) +METHOD(jobject, buildNativeQuery, jstring query) { - auto cQuery = TO_C(query); - try { - auto query = std::make_shared(cQuery); - SET_PTR(query); - } catch (std::exception& e) { - LOG("Cannot create query"); - LOG("%s", e.what()); - } + return NEW_RESOURCE(std::make_shared(TO_C(query))); } -DISPOSE - METHOD(jobject, setQuery, jstring query) { THIS->setQuery(TO_C(query)); return thisObj; diff --git a/lib/src/main/cpp/libzim/search.cpp b/lib/src/main/cpp/libzim/search.cpp index 763bb2c..29777c9 100644 --- a/lib/src/main/cpp/libzim/search.cpp +++ b/lib/src/main/cpp/libzim/search.cpp @@ -33,17 +33,14 @@ #define TYPENAME libzim_Search #include -DISPOSE - METHOD(jobject, getResults, jint start, jint maxResults) { auto results = THIS->getResults(TO_C(start), TO_C(maxResults)); - auto obj = NEW_OBJECT("ork/kiwix/libzim/SearchIterator"); - SET_HANDLE(zim::SearchIterator, obj, results.begin()); + auto beginResource = NEW_RESOURCE(results.begin()); + auto endResource = NEW_RESOURCE(results.end()); - // We have to set the nativeHandleEnd but no macro ease our work here. - auto end_ptr = std::make_shared(results.end()); - setPtr(env, obj, std::move(end_ptr), "nativeHandleEnd"); - return obj; + jclass wrapperClass = env->FindClass("org/kiwix/libzim/SearchIterator"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource;org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, beginResource, endResource); } GETTER(jlong, getEstimatedMatches) diff --git a/lib/src/main/cpp/libzim/search_iterator.cpp b/lib/src/main/cpp/libzim/search_iterator.cpp index 6c04c7d..d0c064f 100644 --- a/lib/src/main/cpp/libzim/search_iterator.cpp +++ b/lib/src/main/cpp/libzim/search_iterator.cpp @@ -35,14 +35,6 @@ #include -// We cannot use the default macro to implement `dispose` as we need to delete the end handle -METHOD0(void, dispose) -{ - // Delete end iterator - dispose(env, thisObj, "nativeHandleEnd"); - dispose(env, thisObj); -} - GETTER(jstring, getPath) GETTER(jstring, getTitle) @@ -59,13 +51,13 @@ METHOD0(jstring, getZimId) { METHOD0(jboolean, hasNext) { zim::SearchIterator next(*THIS); next++; - auto end = getPtr(env, thisObj, "nativeHandleEnd"); + auto end = getPtr(env, thisObj, "nativeResourceEnd"); return next == *end; } METHOD0(jobject, next) { (*THIS)++; zim::Entry entry = **THIS; - return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); + return BUILD_WRAPPER(entry); } diff --git a/lib/src/main/cpp/libzim/searcher.cpp b/lib/src/main/cpp/libzim/searcher.cpp index 9810ba2..f6dd609 100644 --- a/lib/src/main/cpp/libzim/searcher.cpp +++ b/lib/src/main/cpp/libzim/searcher.cpp @@ -33,19 +33,14 @@ #define TYPENAME libzim_Searcher #include -METHOD(void, setNativeSearcher, jobject archive) +METHOD(jobject, buildNativeSearcher, jobject archive) { auto cArchive = getPtr(env, archive); - try { - auto searcher = std::make_shared(*cArchive); - SET_PTR(searcher); - } catch (std::exception& e) { - LOG("Cannot create searcher"); - LOG("%s", e.what()); - } + auto searcher = std::make_shared(*cArchive); + return NEW_RESOURCE(searcher); } -METHOD(void, setNativeSearcherMulti, jobjectArray archives) +METHOD(jobject, buildNativeSearcherMulti, jobjectArray archives) { std::vector cArchives; jsize nbArchives = env->GetArrayLength(archives); @@ -54,17 +49,10 @@ METHOD(void, setNativeSearcherMulti, jobjectArray archives) auto cArchive = getPtr(env, archive); cArchives.push_back(*cArchive); } - try { - auto searcher = std::make_shared(cArchives); - SET_PTR(searcher); - } catch (std::exception& e) { - LOG("Cannot create searcher"); - LOG("%s", e.what()); - } + auto searcher = std::make_shared(cArchives); + return NEW_RESOURCE(searcher); } -DISPOSE - METHOD(jobject, addArchive, jobject archive) { auto cArchive = getPtr(env, archive); THIS->addArchive(*cArchive); @@ -73,7 +61,7 @@ METHOD(jobject, addArchive, jobject archive) { METHOD(jobject, search, jobject query) { auto cQuery = getPtr(env, query); - return BUILD_WRAPPER("org/kiwix/libzim/Search", THIS->search(*cQuery)); + return BUILD_WRAPPER(THIS->search(*cQuery)); } METHOD(void, setVerbose, jboolean verbose) { diff --git a/lib/src/main/cpp/libzim/suggestion_item.cpp b/lib/src/main/cpp/libzim/suggestion_item.cpp index 35b1c4f..e550c7f 100644 --- a/lib/src/main/cpp/libzim/suggestion_item.cpp +++ b/lib/src/main/cpp/libzim/suggestion_item.cpp @@ -33,8 +33,6 @@ #define TYPENAME libzim_SuggestionItem #include -DISPOSE - GETTER(jstring, getTitle) GETTER(jstring, getPath) GETTER(jstring, getSnippet) diff --git a/lib/src/main/cpp/libzim/suggestion_iterator.cpp b/lib/src/main/cpp/libzim/suggestion_iterator.cpp index 5181ae1..a5334c6 100644 --- a/lib/src/main/cpp/libzim/suggestion_iterator.cpp +++ b/lib/src/main/cpp/libzim/suggestion_iterator.cpp @@ -33,24 +33,16 @@ #define TYPENAME libzim_SuggestionIterator #include -// We cannot use the default macro to implement `dispose` as we need to delete the end handle -METHOD0(void, dispose) -{ - // Delete end iterator - dispose(env, thisObj, "nativeHandleEnd"); - dispose(env, thisObj); -} - METHOD0(jboolean, hasNext) { NATIVE_TYPE next(*THIS); next++; - auto end = getPtr(env, thisObj, "nativeHandleEnd"); + auto end = getPtr(env, thisObj, "nativeResourceEnd"); return next == *end; } METHOD0(jobject, next) { (*THIS)++; zim::SuggestionItem item = **THIS; - return BUILD_WRAPPER("org/kiwix/libzim/SuggestionItem", item); + return BUILD_WRAPPER(item); } diff --git a/lib/src/main/cpp/libzim/suggestion_search.cpp b/lib/src/main/cpp/libzim/suggestion_search.cpp index 26fa783..66f121e 100644 --- a/lib/src/main/cpp/libzim/suggestion_search.cpp +++ b/lib/src/main/cpp/libzim/suggestion_search.cpp @@ -33,17 +33,14 @@ #define TYPENAME libzim_SuggestionSearch #include -DISPOSE - METHOD(jobject, getResults, jint start, jint maxResults) { auto results = THIS->getResults(TO_C(start), TO_C(maxResults)); - auto obj = NEW_OBJECT("ork/kiwix/libzim/SuggestionIterator"); - SET_HANDLE(zim::SuggestionIterator, obj, results.begin()); + auto beginResource = NEW_RESOURCE(results.begin()); + auto endResource = NEW_RESOURCE(results.end()); - // We have to set the nativeHandleEnd but no macro ease our work here. - auto end_ptr = std::make_shared(results.end()); - setPtr(env, obj, std::move(end_ptr), "nativeHandleEnd"); - return obj; + jclass wrapperClass = env->FindClass("org/kiwix/libzim/SuggestionIterator"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource;org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, beginResource, endResource); } GETTER(jlong, getEstimatedMatches) diff --git a/lib/src/main/cpp/libzim/suggestion_searcher.cpp b/lib/src/main/cpp/libzim/suggestion_searcher.cpp index 792447e..6949a1f 100644 --- a/lib/src/main/cpp/libzim/suggestion_searcher.cpp +++ b/lib/src/main/cpp/libzim/suggestion_searcher.cpp @@ -33,22 +33,16 @@ #include -METHOD(void, setNativeSearcher, jobject archive) +METHOD(jobject, buildNativeSearcher, jobject archive) { auto cArchive = getPtr(env, archive); - try { - auto searcher = std::make_shared(*cArchive); - SET_PTR(searcher); - } catch (std::exception& e) { - LOG("Cannot create searcher"); - LOG("%s", e.what()); - } + auto searcher = std::make_shared(*cArchive); + return NEW_RESOURCE(searcher); } -DISPOSE - METHOD(jobject, suggest, jstring query) { - return BUILD_WRAPPER("org/kiwix/libzim/SuggestionSearch", THIS->suggest(TO_C(query))); + //return BUILD_WRAPPER("org/kiwix/libzim/SuggestionSearch", THIS->suggest(TO_C(query))); + return BUILD_WRAPPER(std::make_shared(THIS->suggest(TO_C(query)))); } METHOD(void, setVerbose, jboolean verbose) { diff --git a/lib/src/main/cpp/macros.h b/lib/src/main/cpp/macros.h index bef647b..aea88e8 100644 --- a/lib/src/main/cpp/macros.h +++ b/lib/src/main/cpp/macros.h @@ -38,5 +38,3 @@ JNIEXPORT retType JNICALL BUILD_METHOD(TYPENAME ,name) ( \ #define GETTER(retType, name) METHOD0(retType, name) { \ return TO_JNI(THIS->name()); \ } - -#define DISPOSE METHOD0(void, dispose) { dispose(env, thisObj); } diff --git a/lib/src/main/cpp/utils.h b/lib/src/main/cpp/utils.h index 00529dd..39ed39b 100644 --- a/lib/src/main/cpp/utils.h +++ b/lib/src/main/cpp/utils.h @@ -37,8 +37,325 @@ #define LOG(...) #endif +#include +#include + using std::shared_ptr; +namespace zim { + class Blob; + class Searcher; + class Query; + class Search; + class SearchIterator; + class SuggestionSearcher; + class SuggestionSearch; + class SuggestionIterator; + class SuggestionItem; + + class Entry; + class Item; +} + +namespace kiwix { + class Library; + class Bookmark; + class Filter; + class Manager; + class Server; +} + +enum class type_id :int { + Archive, + Iterator_path, + Iterator_title, + Iterator_efficient, + Blob, + Searcher, + Query, + Search, + SearchIterator, + SuggestionSearcher, + SuggestionSearch, + SuggestionIterator, + SuggestionItem, + Entry, + Item, + + Library, + Filter, + Manager, + Server, + Book, + Bookmark, + ConstBook, + Illustration, + ConstIllustration +}; + +template +struct WrappedType { }; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Archive; + static constexpr const char* CLASS_NAME = "org/kiwix/libzim/Archive"; +}; + +template<> struct WrappedType>{ + static constexpr const type_id ID = type_id::Iterator_path; + //static constexpr const char* CLASS_NAME = "org/kiwix/libzim/Archive"; +}; + +template<> struct WrappedType>{ + static constexpr const type_id ID = type_id::Iterator_title; + //static constexpr const char* CLASS_NAME = "org/kiwix/libzim/Archive"; +}; + +template<> struct WrappedType>{ + static constexpr const type_id ID = type_id::Iterator_efficient; + //static constexpr const char* CLASS_NAME = "org/kiwix/libzim/Archive"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Blob; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/Blob"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Searcher; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/Searcher"; +}; + + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Search; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/Search"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Query; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/Query"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::SearchIterator; + //static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/Search"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::SuggestionSearcher; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/SuggestionSearcher"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::SuggestionSearch; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/SuggestionSearch"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::SuggestionIterator; + //static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/SuggestionIterator"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::SuggestionItem; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/SuggestionItem"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Entry; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/Entry"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Item; + static constexpr const char* const CLASS_NAME = "org/kiwix/libzim/Item"; +}; + + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Library; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Library"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Bookmark; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Bookmark"; +}; + + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Filter; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Filter"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Manager; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Manager"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Server; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Server"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Book; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Book"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::ConstBook; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Book"; +}; + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::Illustration; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Illustration"; +}; + + +template<> struct WrappedType{ + static constexpr const type_id ID = type_id::ConstIllustration; + static constexpr const char* const CLASS_NAME = "org/kiwix/libkiwix/Illustration"; +}; + + +inline jfieldID getHandleField(JNIEnv* env, jobject obj, const char* handleName) +{ + jclass c = env->GetObjectClass(obj); + // J is the type signature for long: + return env->GetFieldID(c, handleName, "J"); +} + + +template +inline jobject newResource(JNIEnv* env, T&& reference) { + auto ptr = std::make_shared::type>(std::move(reference)); + return newResource(env, std::move(ptr)); +} + +template +inline jobject newResource(JNIEnv* env, shared_ptr&& ptr) { + jclass wrapperClass = env->FindClass("org/kiwix/Wrapper/Resource"); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(IL)V"); + // allocate a shared_ptr on the head + shared_ptr* handle = new shared_ptr(ptr); + jobject wrapper = env->NewObject(wrapperClass, initMethod, static_cast(WrappedType::ID), reinterpret_cast(handle)); + return wrapper; +} +#define NEW_RESOURCE(SHARED_PTR) newResource(env, std::move(SHARED_PTR)); + + +inline void deleteResource(JNIEnv* env, jobject resource) { + jclass resourceClass = env->GetObjectClass(resource); + + jfieldID handleFieldId = env->GetFieldID(resourceClass, "nativeHandle", "J"); + auto handle_ptr = env->GetLongField(resource, handleFieldId); + + // We now need to know the type of the handle. + jfieldID typeFieldId = env->GetFieldID(resourceClass, "classid", "I"); + auto type_id = static_cast(env->GetIntField(resource, typeFieldId)); + + switch (type_id) { + case type_id::Archive: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Iterator_path: + delete reinterpret_cast>*>(handle_ptr); + break; + case type_id::Iterator_title: + delete reinterpret_cast>*>(handle_ptr); + break; + case type_id::Iterator_efficient: + delete reinterpret_cast>*>(handle_ptr); + break; + case type_id::Blob: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Searcher: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Query: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Search: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::SearchIterator: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::SuggestionSearcher: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::SuggestionSearch: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::SuggestionIterator: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::SuggestionItem: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Entry: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Item: + delete reinterpret_cast*>(handle_ptr); + break; + + case type_id::Library: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Bookmark: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Filter: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Manager: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Server: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Book: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::ConstBook: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::Illustration: + delete reinterpret_cast*>(handle_ptr); + break; + case type_id::ConstIllustration: + delete reinterpret_cast*>(handle_ptr); + break; + }; +} + +template +shared_ptr getPtr(JNIEnv* env, jobject thisObj, const char* resourceField = "nativeResource") +{ + jclass thisClass = env->GetObjectClass(thisObj); + jfieldID resourceFieldId = env->GetFieldID(thisClass, resourceField, "org/kiwix/Wrapper/Resource"); + jobject resource = env->GetObjectField(thisObj, resourceFieldId); + + // This may be Wrapper.Resource or IterWrapper.Resource + jclass resourceClass = env->GetObjectClass(resource); + jfieldID handleFieldId = env->GetFieldID(resourceClass, "nativeHandle", "J"); + auto handle_ptr = env->GetLongField(resource, handleFieldId); + + // Let's check that asked type is same that the one registered in the resource. + jfieldID typeFieldId = env->GetFieldID(resourceClass, "classid", "I"); + auto type_id = static_cast(env->GetIntField(resource, typeFieldId)); + assert(type_id == WrappedType::ID); + + auto handle = reinterpret_cast*>(handle_ptr); + return *handle; +} + + // Here is the wrapping structure. // All java class wrapping a `Native` instance must contain a pointer (cast as a long (J)) called "nativeHandle". // They also need a constructor taking no argument (or they can, but helper here cannot be used.) @@ -58,9 +375,8 @@ inline jobject newObject(const char* className, JNIEnv* env) { } #define NEW_OBJECT(CLASSNAME) newObject(CLASSNAME, env) - // Set the pointer to the wrapped object. -template +/*template inline void setPtr(JNIEnv* env, jobject thisObj, shared_ptr&& ptr, const char* handleName = "nativeHandle") { jclass thisClass = env->GetObjectClass(thisObj); @@ -71,19 +387,20 @@ inline void setPtr(JNIEnv* env, jobject thisObj, shared_ptr&& ptr, const char shared_ptr* handle = new shared_ptr(ptr); env->SetLongField(thisObj, fieldId, reinterpret_cast(handle)); } -#define SET_PTR(SHARED_PTR) setPtr(env, thisObj, std::move(SHARED_PTR)) +#define SET_PTR(SHARED_PTR) setPtr(env, thisObj, std::move(SHARED_PTR))*/ // This create a object and set it in the wrapper -template +/*template inline void setHandle(JNIEnv* env, jobject thisObj, Args && ...args) { auto ptr = std::make_shared(std::forward(args)...); setPtr(env, thisObj, std::move(ptr)); } -#define SET_HANDLE(NATIVE_TYPE, OBJ, VALUE) setHandle(env, OBJ, VALUE) +#define SET_HANDLE(NATIVE_TYPE, OBJ, VALUE) setHandle(env, OBJ, VALUE)*/ // Return a shared_ptr for the handle +/* template shared_ptr getPtr(JNIEnv* env, jobject thisObj, const char* handleName = "nativeHandle") { @@ -92,7 +409,7 @@ shared_ptr getPtr(JNIEnv* env, jobject thisObj, const char* handleName = "nat auto handle = reinterpret_cast*>(env->GetLongField(thisObj, fidNumber)); return *handle; } -#define GET_PTR(NATIVE_TYPE) getPtr(env, thisObj) +#define GET_PTR(NATIVE_TYPE) getPtr(env, thisObj)*/ // Delete the heap allocated handle template @@ -107,12 +424,6 @@ void dispose(JNIEnv* env, jobject thisObj, const char* handleName = "nativeHandl env->SetLongField(thisObj, fieldId, 0); } -inline jfieldID getHandleField(JNIEnv* env, jobject obj, const char* handleName) -{ - jclass c = env->GetObjectClass(obj); - // J is the type signature for long: - return env->GetFieldID(c, handleName, "J"); -} inline jobjectArray createArray(JNIEnv* env, size_t length, const std::string& type_sig) { @@ -120,15 +431,28 @@ inline jobjectArray createArray(JNIEnv* env, size_t length, const std::string& t return env->NewObjectArray(length, c, NULL); } + + template -inline jobject buildWrapper(JNIEnv* env, const char* class_name, T&& obj, const char* handleName = "nativeHandle") { - auto wrapper = newObject(class_name, env); - auto ptr = std::make_shared(std::move(obj)); - setPtr(env, wrapper, std::move(ptr)); - return wrapper; +inline jobject buildWrapper(JNIEnv* env, std::shared_ptr&& ptr) { + auto resource = newResource(env, std::move(ptr)); + jclass wrapperClass = env->FindClass(WrappedType::CLASS_NAME); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, resource); } -#define BUILD_WRAPPER(CLASSNAME, OBJ) buildWrapper(env, CLASSNAME, std::move(OBJ)) +template +inline jobject buildWrapper(JNIEnv* env, T&& obj) { + auto resource = newResource(env, std::move(obj)); + jclass wrapperClass = env->FindClass(WrappedType::CLASS_NAME); + jmethodID initMethod = env->GetMethodID(wrapperClass, "", "(org/kiwix/Wrapper/Resource)V"); + return env->NewObject(wrapperClass, initMethod, resource); +} +#define BUILD_WRAPPER(OBJ) buildWrapper(env, std::move(OBJ)) +#define CATCH(MESSAGE) catch (...) { \ + jclass exceptionClass = env->FindClass("java/lang/RuntimeException"); \ + env->ThrowNew(exceptionClass, MESSAGE); \ +} // --------------------------------------------------------------------------- diff --git a/lib/src/main/cpp/wrapper.cpp b/lib/src/main/cpp/wrapper.cpp new file mode 100644 index 0000000..af1599a --- /dev/null +++ b/lib/src/main/cpp/wrapper.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include "org_kiwix_Wrapper_Resource.h" +#include "org_kiwix_IterWrapper_Resource.h" + +#include + +#include + +#include + +#define CLASSNAME "org/kiwix/Wrapper" +#define TYPENAME libzim_Item +#include + +/* + * Class: org_kiwix_Wrapper_Resource + * Method: dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_kiwix_Wrapper_00024Resource_dispose + (JNIEnv *env, jobject resource) { + deleteResource(env, resource); +} + + +/* + * Class: org_kiwix_IterWrapper_Resource + * Method: dispose + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_kiwix_IterWrapper_00024Resource_dispose + (JNIEnv *env , jobject resource) { + deleteResource(env, resource); +} diff --git a/lib/src/main/java/org/kiwix/IterWrapper.java b/lib/src/main/java/org/kiwix/IterWrapper.java new file mode 100644 index 0000000..9a9ea2b --- /dev/null +++ b/lib/src/main/java/org/kiwix/IterWrapper.java @@ -0,0 +1,46 @@ + +package org.kiwix; + +import java.lang.ref.Cleaner; + +public class IterWrapper implements AutoCloseable { + private static final Cleaner cleaner = Cleaner.create(); + protected static class Resource implements Runnable { + Resource(int classid, long nativeHandle) { + this.classid = classid; + this.nativeHandle = nativeHandle; + } + + public void run() { + dispose(); + } + // The pointer (as a long) to the native handle (the shared_ptr) + private long nativeHandle; + + // The name of the class. + // We need it to cast our pointer to the right type. + private int classid; + + // The native method wich will actually delete the cpp resource. + private native void dispose(); + } + + + private final Resource nativeResourceBegin; + private final Cleaner.Cleanable cleanableBegin; + + private final Resource nativeResourceEnd; + private final Cleaner.Cleanable cleanableEnd; + + public IterWrapper(Resource resourceBegin, Resource resourceEnd) { + this.nativeResourceBegin = resourceBegin; + this.cleanableBegin = cleaner.register(this, nativeResourceBegin); + this.nativeResourceEnd = resourceEnd; + this.cleanableEnd = cleaner.register(this, nativeResourceEnd); + } + + public void close() { + cleanableBegin.clean(); + cleanableEnd.clean(); + } +} diff --git a/lib/src/main/java/org/kiwix/Wrapper.java b/lib/src/main/java/org/kiwix/Wrapper.java new file mode 100644 index 0000000..22b2ce9 --- /dev/null +++ b/lib/src/main/java/org/kiwix/Wrapper.java @@ -0,0 +1,40 @@ + +package org.kiwix; + +import java.lang.ref.Cleaner; + +public class Wrapper implements AutoCloseable { + private static final Cleaner cleaner = Cleaner.create(); + protected static class Resource implements Runnable { + Resource(int classid, long nativeHandle) { + this.classid = classid; + this.nativeHandle = nativeHandle; + } + + public void run() { + dispose(); + } + // The pointer (as a long) to the native handle (the shared_ptr) + private long nativeHandle; + + // The name of the class. + // We need it to cast our pointer to the right type. + private int classid; + + // The native method wich will actually delete the cpp resource. + private native void dispose(); + } + + + private final Resource nativeResource; + private final Cleaner.Cleanable cleanable; + + public Wrapper(Resource resource) { + this.nativeResource = resource; + this.cleanable = cleaner.register(this, nativeResource); + } + + public void close() { + cleanable.clean(); + } +} diff --git a/lib/src/main/java/org/kiwix/libkiwix/Book.java b/lib/src/main/java/org/kiwix/libkiwix/Book.java index a7ddc88..ab6e0ff 100644 --- a/lib/src/main/java/org/kiwix/libkiwix/Book.java +++ b/lib/src/main/java/org/kiwix/libkiwix/Book.java @@ -3,19 +3,15 @@ import org.kiwix.libzim.Archive; import org.kiwix.libkiwix.Illustration; +import org.kiwix.Wrapper; -public class Book +public class Book extends Wrapper { - public Book() { allocate(); } - + public Book(Wrapper.Resource res) { super(res); } public native void update(Book book); public native void update(Archive archive); - - @Override - protected void finalize() { dispose(); } - public native String getId(); public native String getPath(); public native String getHumanReadableIdFromPath(); @@ -45,8 +41,4 @@ public class Book public native Illustration[] getIllustrations(); public native Illustration getIllustration(int size); - - private native void allocate(); - private native void dispose(); - private long nativeHandle; } diff --git a/lib/src/main/java/org/kiwix/libkiwix/Bookmark.java b/lib/src/main/java/org/kiwix/libkiwix/Bookmark.java index a6c1d4c..ccdacb2 100644 --- a/lib/src/main/java/org/kiwix/libkiwix/Bookmark.java +++ b/lib/src/main/java/org/kiwix/libkiwix/Bookmark.java @@ -19,10 +19,12 @@ package org.kiwix.libkiwix; -public class Bookmark +import org.kiwix.Wrapper; + +public class Bookmark extends Wrapper { public Bookmark() { - setNativeBookmark(); + super(buildNativeBookmark()); } public native void setBookId(String bookId); @@ -39,15 +41,6 @@ public Bookmark() { public native String getLanguage(); public native String getDate(); - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - // A pointer (as a long) to a native Handle - private native void setNativeBookmark(); - private long nativeHandle; + private native static Wrapper.Resource buildNativeBookmark(); } diff --git a/lib/src/main/java/org/kiwix/libkiwix/Filter.java b/lib/src/main/java/org/kiwix/libkiwix/Filter.java index 458856d..d43a35e 100644 --- a/lib/src/main/java/org/kiwix/libkiwix/Filter.java +++ b/lib/src/main/java/org/kiwix/libkiwix/Filter.java @@ -19,8 +19,13 @@ package org.kiwix.libkiwix; -public class Filter +import org.kiwix.Wrapper; + +public class Filter extends Wrapper { + public Filter() { + super(getNativeFilter()); + } public native Filter local(boolean accept); public native Filter remote(boolean accept); @@ -33,12 +38,5 @@ public class Filter public native Filter maxSize(long size); public native Filter query(String query); - - public Filter() { allocate(); } - - @Override - protected void finalize() { dispose(); } - private native void allocate(); - private native void dispose(); - private long nativeHandle; + private native static Wrapper.Resource getNativeFilter(); } diff --git a/lib/src/main/java/org/kiwix/libkiwix/Illustration.java b/lib/src/main/java/org/kiwix/libkiwix/Illustration.java index 771a4e2..c369b87 100644 --- a/lib/src/main/java/org/kiwix/libkiwix/Illustration.java +++ b/lib/src/main/java/org/kiwix/libkiwix/Illustration.java @@ -1,7 +1,8 @@ package org.kiwix.libkiwix; +import org.kiwix.Wrapper; -public class Illustration +public class Illustration extends Wrapper { public native int width(); public native int height(); @@ -9,9 +10,7 @@ public class Illustration public native String url(); public native String getData(); - @Override - protected void finalize() { dispose(); } - private native void dispose(); - private long nativeHandle; + + private Illustration(Wrapper.Resource res) { super(res); } } diff --git a/lib/src/main/java/org/kiwix/libkiwix/Library.java b/lib/src/main/java/org/kiwix/libkiwix/Library.java index e9f4c47..9497b73 100644 --- a/lib/src/main/java/org/kiwix/libkiwix/Library.java +++ b/lib/src/main/java/org/kiwix/libkiwix/Library.java @@ -24,12 +24,13 @@ import org.kiwix.libkiwix.Book; import org.kiwix.libkiwix.JNIKiwixException; import org.kiwix.libkiwix.Bookmark; +import org.kiwix.Wrapper; -public class Library +public class Library extends Wrapper { public Library() { - setNativeHandler(); + super(buildNativeLibrary()); } public native boolean addBook(Book book) throws JNIKiwixException; @@ -58,9 +59,5 @@ public Library() public native boolean removeBookmark(String zimId, String url); public native Bookmark[] getBookmarks(boolean onlyValidBookmarks); - @Override - protected void finalize() { dispose(); } - private native void setNativeHandler(); - private native void dispose(); - private long nativeHandle; + private native static Wrapper.Resource buildNativeLibrary(); } diff --git a/lib/src/main/java/org/kiwix/libkiwix/Manager.java b/lib/src/main/java/org/kiwix/libkiwix/Manager.java index 5ddbc08..afbb83f 100644 --- a/lib/src/main/java/org/kiwix/libkiwix/Manager.java +++ b/lib/src/main/java/org/kiwix/libkiwix/Manager.java @@ -20,8 +20,9 @@ package org.kiwix.libkiwix; import org.kiwix.libkiwix.Library; +import org.kiwix.Wrapper; -public class Manager +public class Manager extends Wrapper { /** * Read a `library.xml` file and add books in the library. @@ -76,15 +77,11 @@ public native String addBookFromPath(String pathToOpen, boolean checkMetaData); public Manager(Library library) { - allocate(library); + super(buildNativeManager(library)); _library = library; } private Library _library; - @Override - protected void finalize() { dispose(); } - private native void allocate(Library library); - private native void dispose(); - private long nativeHandle; + private native static Wrapper.Resource buildNativeManager(Library library); } diff --git a/lib/src/main/java/org/kiwix/libkiwix/Server.java b/lib/src/main/java/org/kiwix/libkiwix/Server.java index b8b5a78..4dadb83 100644 --- a/lib/src/main/java/org/kiwix/libkiwix/Server.java +++ b/lib/src/main/java/org/kiwix/libkiwix/Server.java @@ -21,8 +21,9 @@ import org.kiwix.libkiwix.JNIKiwixException; import org.kiwix.libkiwix.Library; +import org.kiwix.Wrapper; -public class Server +public class Server extends Wrapper { public native void setRoot(String root); @@ -42,14 +43,8 @@ public class Server public Server(Library library) { - setNativeServer(library); + super(buildNativeServer(library)); } - @Override - protected void finalize() { dispose(); } - - - private native void setNativeServer(Library library); - private native void dispose(); - private long nativeHandle; + private native static Wrapper.Resource buildNativeServer(Library library); } diff --git a/lib/src/main/java/org/kiwix/libzim/Archive.java b/lib/src/main/java/org/kiwix/libzim/Archive.java index 735cc79..f88c61c 100644 --- a/lib/src/main/java/org/kiwix/libzim/Archive.java +++ b/lib/src/main/java/org/kiwix/libzim/Archive.java @@ -23,34 +23,26 @@ import org.kiwix.libzim.Entry; import org.kiwix.libzim.Item; import org.kiwix.libzim.EntryIterator; +import org.kiwix.Wrapper; import java.io.FileDescriptor; -public class Archive +public class Archive extends Wrapper { public Archive(String filename) throws ZimFileFormatException { - setNativeArchive(filename); - if (nativeHandle == 0) { - throw new ZimFileFormatException("Cannot open zimfile "+filename); - } + super(buildNativeArchive(filename)); } public Archive(FileDescriptor fd) throws ZimFileFormatException { - setNativeArchiveByFD(fd); - if (nativeHandle == 0) { - throw new ZimFileFormatException("Cannot open zimfile by fd "+fd.toString()); - } + super(buildNativeArchiveByFD(fd)); } public Archive(FileDescriptor fd, long offset, long size) throws ZimFileFormatException { - setNativeArchiveEmbedded(fd, offset, size); - if (nativeHandle == 0) { - throw new ZimFileFormatException(String.format("Cannot open embedded zimfile (fd=%s, offset=%d, size=%d)", fd, offset, size)); - } + super(buildNativeArchiveEmbedded(fd, offset, size)); } public native String getFilename(); @@ -100,18 +92,7 @@ public Archive(FileDescriptor fd, long offset, long size) public native EntryIterator findByTitle(String path); - private native void setNativeArchive(String filename); - private native void setNativeArchiveByFD(FileDescriptor fd); - private native void setNativeArchiveEmbedded(FileDescriptor fd, long offset, long size); - - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; + private native static Wrapper.Resource buildNativeArchive(String filename); + private native static Wrapper.Resource buildNativeArchiveByFD(FileDescriptor fd); + private native static Wrapper.Resource buildNativeArchiveEmbedded(FileDescriptor fd, long offset, long size); } diff --git a/lib/src/main/java/org/kiwix/libzim/Blob.java b/lib/src/main/java/org/kiwix/libzim/Blob.java index 93852f2..a8470eb 100644 --- a/lib/src/main/java/org/kiwix/libzim/Blob.java +++ b/lib/src/main/java/org/kiwix/libzim/Blob.java @@ -20,21 +20,13 @@ package org.kiwix.libzim; import org.kiwix.libzim.Blob; +import org.kiwix.Wrapper; -public class Blob +public class Blob extends Wrapper { + private Blob(Wrapper.Resource res) { + super(res); + } public native String getData(); public native long size(); - - - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; } diff --git a/lib/src/main/java/org/kiwix/libzim/Entry.java b/lib/src/main/java/org/kiwix/libzim/Entry.java index 052a9df..e3e2e1f 100644 --- a/lib/src/main/java/org/kiwix/libzim/Entry.java +++ b/lib/src/main/java/org/kiwix/libzim/Entry.java @@ -20,9 +20,13 @@ package org.kiwix.libzim; import org.kiwix.libzim.Item; +import org.kiwix.Wrapper; -public class Entry +public class Entry extends Wrapper { + private Entry(Wrapper.Resource res) { + super(res); + } public native boolean isRedirect(); public native String getTitle(); public native String getPath(); @@ -30,14 +34,4 @@ public class Entry public native Item getItem(boolean follow); public native Item getRedirect(); public native Entry getRedirectEntry(); - - @Override - protected void finalize() { dispose(); } - -///--------- The wrapper thing - // To delete our native wrapper - private native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; } diff --git a/lib/src/main/java/org/kiwix/libzim/EntryIterator.java b/lib/src/main/java/org/kiwix/libzim/EntryIterator.java index b072de1..7214cdc 100644 --- a/lib/src/main/java/org/kiwix/libzim/EntryIterator.java +++ b/lib/src/main/java/org/kiwix/libzim/EntryIterator.java @@ -20,29 +20,17 @@ package org.kiwix.libzim; import java.util.Iterator; +import org.kiwix.IterWrapper; -public class EntryIterator implements Iterator +public class EntryIterator extends IterWrapper implements Iterator { - private EntryIterator(int order) { + private EntryIterator(int order, Resource nativeResourceBegin, Resource nativeResourceEnd) { + super(nativeResourceBegin, nativeResourceEnd); this.order = order; } public native boolean hasNext(); public native Entry next(); - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - // A marker of the order used for this iterator private int order; - - // A pointer (as a long) to a native Handle - private long nativeHandle; - - // A pointer (as a long) to the native end - private long nativeHandleEnd; } diff --git a/lib/src/main/java/org/kiwix/libzim/Item.java b/lib/src/main/java/org/kiwix/libzim/Item.java index 2b59b82..19f0ac4 100644 --- a/lib/src/main/java/org/kiwix/libzim/Item.java +++ b/lib/src/main/java/org/kiwix/libzim/Item.java @@ -21,9 +21,13 @@ import org.kiwix.libzim.Blob; import org.kiwix.libzim.DirectAccessInfo; +import org.kiwix.Wrapper; -public class Item +public class Item extends Wrapper { + private Item(Wrapper.Resource res) { + super(res); + } public native String getTitle(); public native String getPath(); public native String getMimetype(); @@ -32,14 +36,4 @@ public class Item public native long getSize(); public native DirectAccessInfo getDirectAccessInformation(); - - @Override - protected void finalize() { dispose(); } - -///--------- The wrapper thing - // To delete our native wrapper - private native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; } diff --git a/lib/src/main/java/org/kiwix/libzim/Query.java b/lib/src/main/java/org/kiwix/libzim/Query.java index 75599b5..ff117b1 100644 --- a/lib/src/main/java/org/kiwix/libzim/Query.java +++ b/lib/src/main/java/org/kiwix/libzim/Query.java @@ -19,24 +19,15 @@ package org.kiwix.libzim; -public class Query +import org.kiwix.Wrapper; + +public class Query extends Wrapper { public Query(String query) { - setNativeQuery(query); + super(buildNativeQuery(query)); } public native Query setQuery(String query); public native Query setGeorange(float latitude, float longitute, float distance); - - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private native long setNativeQuery(String query); - private long nativeHandle; + private native static Wrapper.Resource buildNativeQuery(String query); } diff --git a/lib/src/main/java/org/kiwix/libzim/Search.java b/lib/src/main/java/org/kiwix/libzim/Search.java index d078886..6f05906 100644 --- a/lib/src/main/java/org/kiwix/libzim/Search.java +++ b/lib/src/main/java/org/kiwix/libzim/Search.java @@ -20,20 +20,13 @@ package org.kiwix.libzim; import org.kiwix.libzim.SearchIterator; +import org.kiwix.Wrapper; -public class Search +public class Search extends Wrapper { + private Search(Wrapper.Resource res) { + super(res); + } public native SearchIterator getResults(int start, int maxResults); public native long getEstimatedMatches(); - - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; } diff --git a/lib/src/main/java/org/kiwix/libzim/SearchIterator.java b/lib/src/main/java/org/kiwix/libzim/SearchIterator.java index 0a73912..b84a3ff 100644 --- a/lib/src/main/java/org/kiwix/libzim/SearchIterator.java +++ b/lib/src/main/java/org/kiwix/libzim/SearchIterator.java @@ -35,18 +35,4 @@ public class SearchIterator implements Iterator public native boolean hasNext(); public native Entry next(); - - - @Override - protected void finalize() { dispose(); } - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; - - // A pointer (as a long) to the native end - private long nativeHandleEnd; } diff --git a/lib/src/main/java/org/kiwix/libzim/Searcher.java b/lib/src/main/java/org/kiwix/libzim/Searcher.java index cd3c4d6..33d973f 100644 --- a/lib/src/main/java/org/kiwix/libzim/Searcher.java +++ b/lib/src/main/java/org/kiwix/libzim/Searcher.java @@ -24,41 +24,25 @@ import org.kiwix.libzim.Search; import org.kiwix.libzim.Query; import java.io.FileDescriptor; +import org.kiwix.Wrapper; -public class Searcher +public class Searcher extends Wrapper { public Searcher(Archive archive) throws Exception { - setNativeSearcher(archive); - if (nativeHandle == 0) { - throw new Exception("Cannot create searcher"); - } + super(buildNativeSearcher(archive)); } public Searcher(Archive[] archives) throws Exception { - setNativeSearcherMulti(archives); - if (nativeHandle == 0) { - throw new Exception("Cannot create searcher"); - } + super(buildNativeSearcherMulti(archives)); } public native Searcher addArchive(Archive archive); public native Search search(Query query); public native void setVerbose(boolean verbose); - private native void setNativeSearcher(Archive archive); - private native void setNativeSearcherMulti(Archive[] archives); - - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; + private native static Wrapper.Resource buildNativeSearcher(Archive archive); + private native static Wrapper.Resource buildNativeSearcherMulti(Archive[] archives); } diff --git a/lib/src/main/java/org/kiwix/libzim/SuggestionItem.java b/lib/src/main/java/org/kiwix/libzim/SuggestionItem.java index 4021cd4..d7f1af1 100644 --- a/lib/src/main/java/org/kiwix/libzim/SuggestionItem.java +++ b/lib/src/main/java/org/kiwix/libzim/SuggestionItem.java @@ -18,21 +18,14 @@ */ package org.kiwix.libzim; +import org.kiwix.Wrapper; -public class SuggestionItem +public class SuggestionItem extends Wrapper { public native String getTitle(); public native String getPath(); public native String getSnippet(); public native boolean hasSnippet(); - @Override - protected void finalize() { dispose(); } - -///--------- The wrapper thing - // To delete our native wrapper - private native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; + private SuggestionItem(Wrapper.Resource res) { super(res); } } diff --git a/lib/src/main/java/org/kiwix/libzim/SuggestionIterator.java b/lib/src/main/java/org/kiwix/libzim/SuggestionIterator.java index 20d0298..8ed2e55 100644 --- a/lib/src/main/java/org/kiwix/libzim/SuggestionIterator.java +++ b/lib/src/main/java/org/kiwix/libzim/SuggestionIterator.java @@ -20,24 +20,13 @@ package org.kiwix.libzim; import org.kiwix.libzim.SuggestionItem; +import org.kiwix.IterWrapper; import java.util.Iterator; -public class SuggestionIterator implements Iterator +public class SuggestionIterator extends IterWrapper implements Iterator { public native boolean hasNext(); public native SuggestionItem next(); - @Override - protected void finalize() { dispose(); } - - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; - - // A pointer (as a long) to the native end - private long nativeHandleEnd; + private SuggestionIterator(IterWrapper.Resource begin, IterWrapper.Resource end) { super(begin, end); } } diff --git a/lib/src/main/java/org/kiwix/libzim/SuggestionSearch.java b/lib/src/main/java/org/kiwix/libzim/SuggestionSearch.java index 5d2976b..9a03991 100644 --- a/lib/src/main/java/org/kiwix/libzim/SuggestionSearch.java +++ b/lib/src/main/java/org/kiwix/libzim/SuggestionSearch.java @@ -20,20 +20,12 @@ package org.kiwix.libzim; import org.kiwix.libzim.SuggestionIterator; +import org.kiwix.Wrapper; -public class SuggestionSearch +public class SuggestionSearch extends Wrapper { public native SuggestionIterator getResults(int start, int maxResults); public native long getEstimatedMatches(); - - @Override - protected void finalize() { dispose(); } - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; + private SuggestionSearch(Wrapper.Resource res) { super(res); } } diff --git a/lib/src/main/java/org/kiwix/libzim/SuggestionSearcher.java b/lib/src/main/java/org/kiwix/libzim/SuggestionSearcher.java index c45961e..a103002 100644 --- a/lib/src/main/java/org/kiwix/libzim/SuggestionSearcher.java +++ b/lib/src/main/java/org/kiwix/libzim/SuggestionSearcher.java @@ -23,31 +23,18 @@ import org.kiwix.libzim.Archive; import org.kiwix.libzim.SuggestionSearch; import java.io.FileDescriptor; +import org.kiwix.Wrapper; -public class SuggestionSearcher +public class SuggestionSearcher extends Wrapper { public SuggestionSearcher(Archive archive) throws Exception { - setNativeSearcher(archive); - if (nativeHandle == 0) { - throw new Exception("Cannot create searcher"); - } + super(buildNativeSearcher(archive)); } public native SuggestionSearch suggest(String query); public native void setVerbose(boolean verbose); - private native void setNativeSearcher(Archive archive); - - - @Override - protected void finalize() { dispose(); } - -///--------- The wrapper thing - // To delete our native wrapper - public native void dispose(); - - // A pointer (as a long) to a native Handle - private long nativeHandle; + private native static Wrapper.Resource buildNativeSearcher(Archive archive); }