From 75652d0e9f044c80645e74d779fb4f06bab87913 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Wed, 22 Jan 2020 14:55:32 +0100 Subject: [PATCH] WIP Add a wrapper around the kiwix::manager class. The JNIKiwixManager is used to manage (insertion of book in) the library. It is created, as needed, using an existing Library as input. It is then used to add books, parse library.xml or opds content. Then it can be destruct (and must be) with the `dispose` method. ```java library = JNILibrary(...); manager = JNIManager(library); manager.parseOpds(opdscontent); manager.dispose(); // library contains the books declared in the opds content. // Use the library methods to get the books' info. ``` --- src/android/manager.cpp | 133 ++++++++++++++++++++ src/android/meson.build | 3 + src/android/org/kiwix/kiwixlib/Manager.java | 90 +++++++++++++ src/android/utils.h | 7 +- 4 files changed, 230 insertions(+), 3 deletions(-) create mode 100644 src/android/manager.cpp create mode 100644 src/android/org/kiwix/kiwixlib/Manager.java diff --git a/src/android/manager.cpp b/src/android/manager.cpp new file mode 100644 index 000000000..54bea06f2 --- /dev/null +++ b/src/android/manager.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2020 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 +#include "org_kiwix_kiwixlib_Manager.h" + +#include "manager.h" +#include "utils.h" + + +JNIEXPORT void JNICALL +Java_org_kiwix_kiwixlib_Manager_allocate( + JNIEnv* env, jobject thisObj, jobject libraryObj) +{ + auto lib = Handle::getHandle(env, libraryObj); + allocate(env, thisObj, lib); +} + +JNIEXPORT void JNICALL +Java_org_kiwix_kiwixlib_Manager_dispose(JNIEnv* env, jobject thisObj) +{ + dispose(env, thisObj); +} + +#define MANAGER (getPtr(env, thisObj)) + +/* Kiwix manager functions */ +JNIEXPORT jboolean JNICALL +Java_org_kiwix_kiwixlib_Manager_readFile( + JNIEnv* env, jobject thisObj, jstring path) +{ + auto cPath = jni2c(path, env); + + try { + return MANAGER->readFile(cPath); + } catch (std::exception& e) { + __android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get readFile"); + __android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what()); + } + return false; +} + +JNIEXPORT jboolean JNICALL +Java_org_kiwix_kiwixlib_Manager_readXml( + JNIEnv* env, jobject thisObj, jstring content, jstring libraryPath) +{ + auto cContent = jni2c(content, env); + auto cPath = jni2c(libraryPath, env); + + try { + return MANAGER->readXml(cContent, false, cPath); + } catch (std::exception& e) { + __android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM id"); + __android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what()); + } + + return false; +} + +JNIEXPORT jboolean JNICALL +Java_org_kiwix_kiwixlib_Manager_readOpds( + JNIEnv* env, jobject thisObj, jstring content, jstring urlHost) +{ + auto cContent = jni2c(content, env); + auto cUrl = jni2c(urlHost, env); + + try { + return MANAGER->readOpds(cContent, cUrl); + } catch (std::exception& e) { + __android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM id"); + __android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what()); + } + + return false; +} + +JNIEXPORT jboolean JNICALL +Java_org_kiwix_kiwixlib_Manager_readBookmarkFile( + JNIEnv* env, jobject thisObj, jstring path) +{ + auto cPath = jni2c(path, env); + + try { + return MANAGER->readBookmarkFile(cPath); + } catch (std::exception& e) { + __android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM id"); + __android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what()); + } + + return false; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_Manager_addBookFromPath( + JNIEnv* env, jobject thisObj, + jstring pathToOpen, jstring pathToSave, jstring url, jboolean checkMetaData) +{ + auto cPathToOpen = jni2c(pathToOpen, env); + auto cPathToSave = jni2c(pathToSave, env); + auto cUrl = jni2c(url, env); + jstring id = NULL; + + try { + auto cId = MANAGER->addBookFromPathAndGetId(cPathToOpen, cPathToSave, cUrl, checkMetaData); + if ( !cId.empty() ) { + id = c2jni(cId, env); + } + } catch (std::exception& e) { + __android_log_print(ANDROID_LOG_ERROR, "kiwix", "Unable to get ZIM file size"); + __android_log_print(ANDROID_LOG_ERROR, "kiwix", e.what()); + } + + return id; +} diff --git a/src/android/meson.build b/src/android/meson.build index 0b4fb5c19..fcb09361b 100644 --- a/src/android/meson.build +++ b/src/android/meson.build @@ -4,6 +4,7 @@ kiwix_jni = custom_target('jni', 'org/kiwix/kiwixlib/Book.java', 'org/kiwix/kiwixlib/JNIKiwixReader.java', 'org/kiwix/kiwixlib/JNIKiwixLibrary.java', + 'org/kiwix/kiwixlib/Manager.java', 'org/kiwix/kiwixlib/JNIKiwixSearcher.java', 'org/kiwix/kiwixlib/JNIKiwixServer.java', 'org/kiwix/kiwixlib/JNIKiwixInt.java', @@ -15,6 +16,7 @@ kiwix_jni = custom_target('jni', 'org_kiwix_kiwixlib_Book.h', 'org_kiwix_kiwixlib_JNIKiwixReader.h', 'org_kiwix_kiwixlib_JNIKiwixLibrary.h', + 'org_kiwix_kiwixlib_Manager.h', 'org_kiwix_kiwixlib_JNIKiwixServer.h', 'org_kiwix_kiwixlib_JNIKiwixSearcher.h', 'org_kiwix_kiwixlib_JNIKiwixSearcher_Result.h'], @@ -26,6 +28,7 @@ kiwix_sources += [ 'android/book.cpp', 'android/kiwixreader.cpp', 'android/kiwixlibrary.cpp', + 'android/manager.cpp', 'android/kiwixsearcher.cpp', 'android/kiwixserver.cpp', kiwix_jni] diff --git a/src/android/org/kiwix/kiwixlib/Manager.java b/src/android/org/kiwix/kiwixlib/Manager.java new file mode 100644 index 000000000..a4a1e2830 --- /dev/null +++ b/src/android/org/kiwix/kiwixlib/Manager.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2020 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. + */ + +package org.kiwix.kiwixlib; + +import org.kiwix.kiwixlib.JNIKiwixLibrary; + +public class Manager +{ + /** + * Read a `library.xml` file and add books in the library. + * + * @param path The (utf8) path to the `library.xml` file. + * @return True if the file has been properly parsed. + */ + public native boolean readFile(String path); + + /** + * Load a library content stored in a string (at `library.xml` format). + * + * @param content The content corresponding of the library xml. + * @param libraryPath The library path (used to resolve relative paths) + * @return True if the content has been properly parsed. + */ + public native boolean readXml(String content, String libraryPath); + + /** + * Load a library content stored in a string (at OPDS stream format) + * + * @param content the content of the OPDS stream. + * @param urlHost the url of the stream (used to resolve relative url) + * @return True if the content has been properly parsed. + */ + public native boolean readOpds(String content, String urlHost); + + /** + * Load a bookmark file + * + * @param path The path of the file to read. + * @return True if the content has been properly parsed + */ + public native boolean readBookmarkFile(String path); + + /** + * Add a book to the library. + * + * @param pathToOpen The path of the zim file to add. + * @param pathToSave The path to store in the library in place of + * pathToOpen. + * @param url The url of the book to store in the library + * (useful for kiiwix-serve catalog) + * @param checkMetaData Tell if we check metadata before adding a book to the + * library. + * @return The id of te book if the book has been added to the library. + * Empty string if not. + */ + public native String addBookFromPath(String pathToOpen, + String pathToSave, + String url, + boolean checkMetaData); + + public Manager(JNIKiwixLibrary library) { + allocate(library); + _library = library; + } + + private JNIKiwixLibrary _library; + + @Override + protected void finalize() { dispose(); } + private native void allocate(JNIKiwixLibrary library); + private native void dispose(); + private long nativeHandle; +} diff --git a/src/android/utils.h b/src/android/utils.h index 513dac771..e67fb016b 100644 --- a/src/android/utils.h +++ b/src/android/utils.h @@ -29,12 +29,12 @@ extern pthread_mutex_t globalLock; -template -void allocate(JNIEnv* env, jobject thisObj) +template +void allocate(JNIEnv* env, jobject thisObj, Args && ...args) { jclass thisClass = env->GetObjectClass(thisObj); jfieldID fidNumber = env->GetFieldID(thisClass, "nativeHandle", "J"); - T* ptr = new T(); + T* ptr = new T(std::forward(args)...); env->SetLongField(thisObj, fidNumber, reinterpret_cast(ptr)); } @@ -114,6 +114,7 @@ struct LockedHandle : public Lock { T* operator->() { return h->h; } T* operator*() { return h->h; } operator bool() const { return (h->h != nullptr); } + operator T*() const { return h->h; } }; template