From 8d684cee8e0d95e6a48a78e4370d4247d97f1139 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Mon, 25 Mar 2024 10:05:24 +0100 Subject: [PATCH] Allow `zim::Archive` to be created with a set of File descriptor. --- lib/build.gradle | 3 +- lib/src/main/cpp/libzim/archive.cpp | 65 +++++++++++++++++++ .../main/java/org/kiwix/libzim/Archive.java | 15 +++++ .../main/java/org/kiwix/libzim/FdInput.java | 29 +++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 lib/src/main/java/org/kiwix/libzim/FdInput.java diff --git a/lib/build.gradle b/lib/build.gradle index f912277..93b6029 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -354,7 +354,8 @@ String getLibzimFiles() { "${projectDir}/src/main/java/org/kiwix/libzim/SuggestionSearcher.java " + "${projectDir}/src/main/java/org/kiwix/libzim/SuggestionSearch.java " + "${projectDir}/src/main/java/org/kiwix/libzim/ZimFileFormatException.java " + - "${projectDir}/src/main/java/org/kiwix/libzim/EntryNotFoundException.java" + "${projectDir}/src/main/java/org/kiwix/libzim/EntryNotFoundException.java " + + "${projectDir}/src/main/java/org/kiwix/libzim/FdInput.java" } task buildLinuxBinding(type: Exec) { diff --git a/lib/src/main/cpp/libzim/archive.cpp b/lib/src/main/cpp/libzim/archive.cpp index 5d61a19..2b976e5 100644 --- a/lib/src/main/cpp/libzim/archive.cpp +++ b/lib/src/main/cpp/libzim/archive.cpp @@ -62,6 +62,22 @@ int jni2fd(const jobject& fdObj, JNIEnv* env) return env->GetIntField(fdObj, field_fd); } +zim::FdInput jni2fdInput(const jobject& fdInputObj, JNIEnv* env) +{ + jclass class_fdesc = env->FindClass("org/kiwix/FdInput"); + jfieldID field_id = env->GetFieldID(class_fdesc, "fd", "java/io/FileDescriptor"); + jobject fdObj = env->GetField(fdInputObj, field_id); + int fd = jni2fd(fdObj, env); + + field_id = env->GetFieldID(class_fdesc, "offset", "J"); + long offset = env->GetLongField(fdObj, field_id); + + field_id = env->GetFieldID(class_fdesc, "size", "J"); + long size = env->GetLongField(fdObj, field_id); + + return zim::FdInput(fd, offset, size); +} + } // unnamed namespace JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveByFD( @@ -104,6 +120,55 @@ JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveEmbedded( #endif } CATCH_EXCEPTION() +JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveEmbeddedFd( + JNIEnv* env, jobject thisObj, jobject fdObj) try +{ +#ifndef _WIN32 + auto fdInput = jni2fdInput(fdObj, env); + + LOG("Attempting to create reader with fd: %d", fdInput); + try { + auto archive = std::make_shared(fdInput); + SET_PTR(archive); + } catch (std::exception& e) { + LOG("Error opening ZIM file"); + LOG("%s", e.what()); + } +#else + jclass exception = env->FindClass("java/lang/UnsupportedOperationException"); + env->ThrowNew(exception, "org.kiwix.libzim.Archive.setNativeArchiveEmbedded() is not supported under Windows"); +#endif +} CATCH_EXCEPTION() + + +JNIEXPORT void JNICALL Java_org_kiwix_libzim_Archive_setNativeArchiveEmbeddedFds( + JNIEnv* env, jobject thisObj, jobjectArray fdsObj) try +{ +#ifndef _WIN32 + + jsize length = env->GetArrayLength(fdsObj); + std::vector v(length); + + int i; + for(i = 0; iGetObjectArrayElement(fdsObj, i); + auto fdInput = jni2fdInput(fdObj, env); + v.push_pack(fdInput); + } + + try { + auto archive = std::make_shared(v); + SET_PTR(archive); + } catch (std::exception& e) { + LOG("Error opening ZIM file"); + LOG("%s", e.what()); + } +#else + jclass exception = env->FindClass("java/lang/UnsupportedOperationException"); + env->ThrowNew(exception, "org.kiwix.libzim.Archive.setNativeArchiveEmbedded() is not supported under Windows"); +#endif +} CATCH_EXCEPTION() + DISPOSE GETTER(jstring, getFilename) diff --git a/lib/src/main/java/org/kiwix/libzim/Archive.java b/lib/src/main/java/org/kiwix/libzim/Archive.java index 7ac9663..a15bf4d 100644 --- a/lib/src/main/java/org/kiwix/libzim/Archive.java +++ b/lib/src/main/java/org/kiwix/libzim/Archive.java @@ -23,6 +23,7 @@ import org.kiwix.libzim.ZimFileFormatException; import org.kiwix.libzim.Entry; import org.kiwix.libzim.Item; import org.kiwix.libzim.EntryIterator; +import org.kiwix.libzim.FdInput; import java.io.FileDescriptor; public class Archive @@ -44,6 +45,18 @@ public class Archive setNativeArchiveEmbedded(fd, offset, size); } + public Archive(FdInput fd) + throws ZimFileFormatException + { + setNativeArchiveEmbeddedFd(fd); + } + + public Archive(FdInput[] fds) + throws ZimFileFormatException + { + setNativeArchiveEmbeddedFds(fds); + } + public native String getFilename(); public native long getFilesize(); public native int getAllEntryCount(); @@ -94,6 +107,8 @@ public class Archive private native void setNativeArchive(String filename); private native void setNativeArchiveByFD(FileDescriptor fd); private native void setNativeArchiveEmbedded(FileDescriptor fd, long offset, long size); + private native void setNativeArchiveEmbeddedFd(FdInput fd); + private native void setNativeArchiveEmbeddedFds(FdInput[] fds); @Override protected void finalize() { dispose(); } diff --git a/lib/src/main/java/org/kiwix/libzim/FdInput.java b/lib/src/main/java/org/kiwix/libzim/FdInput.java new file mode 100644 index 0000000..c8f1c84 --- /dev/null +++ b/lib/src/main/java/org/kiwix/libzim/FdInput.java @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package org.kiwix.libzim; + +import java.io.FileDescriptor; + +public class FdInput +{ + public FileDescriptor fd; + public long offset; + public long size; +}