diff --git a/jni/NativeFormats/JavaNativeFormatPlugin.cpp b/jni/NativeFormats/JavaNativeFormatPlugin.cpp index 2f7f06621..b1c97af42 100644 --- a/jni/NativeFormats/JavaNativeFormatPlugin.cpp +++ b/jni/NativeFormats/JavaNativeFormatPlugin.cpp @@ -42,51 +42,38 @@ static shared_ptr findCppPlugin(jobject base) { static void fillUids(JNIEnv* env, jobject javaBook, Book &book) { const UIDList &uids = book.uids(); for (UIDList::const_iterator it = uids.begin(); it != uids.end(); ++it) { - jstring type = AndroidUtil::createJavaString(env, (*it)->Type); - jstring id = AndroidUtil::createJavaString(env, (*it)->Id); - AndroidUtil::Method_Book_addUid->call(javaBook, type, id); - env->DeleteLocalRef(id); - env->DeleteLocalRef(type); + JString type(env, (*it)->Type); + JString id(env, (*it)->Id); + AndroidUtil::Method_Book_addUid->call(javaBook, type.j(), id.j()); } } static void fillMetaInfo(JNIEnv* env, jobject javaBook, Book &book) { - jstring javaString; + JString title(env, book.title()); + AndroidUtil::Method_Book_setTitle->call(javaBook, title.j()); - javaString = AndroidUtil::createJavaString(env, book.title()); - AndroidUtil::Method_Book_setTitle->call(javaBook, javaString); - env->DeleteLocalRef(javaString); - - javaString = AndroidUtil::createJavaString(env, book.language()); - if (javaString != 0) { - AndroidUtil::Method_Book_setLanguage->call(javaBook, javaString); - env->DeleteLocalRef(javaString); + JString language(env, book.language()); + if (language.j() != 0) { + AndroidUtil::Method_Book_setLanguage->call(javaBook, language.j()); } - javaString = AndroidUtil::createJavaString(env, book.encoding()); - if (javaString != 0) { - AndroidUtil::Method_Book_setEncoding->call(javaBook, javaString); - env->DeleteLocalRef(javaString); + JString encoding(env, book.encoding()); + if (encoding.j() != 0) { + AndroidUtil::Method_Book_setEncoding->call(javaBook, encoding.j()); } - javaString = AndroidUtil::createJavaString(env, book.seriesTitle()); - if (javaString != 0) { - jstring indexString = AndroidUtil::createJavaString(env, book.indexInSeries()); - AndroidUtil::Method_Book_setSeriesInfo->call(javaBook, javaString, indexString); - if (indexString != 0) { - env->DeleteLocalRef(indexString); - } - env->DeleteLocalRef(javaString); + JString seriesTitle(env, book.seriesTitle()); + if (seriesTitle.j() != 0) { + JString indexString(env, book.indexInSeries()); + AndroidUtil::Method_Book_setSeriesInfo->call(javaBook, seriesTitle.j(), indexString.j()); } const AuthorList &authors = book.authors(); for (std::size_t i = 0; i < authors.size(); ++i) { const Author &author = *authors[i]; - javaString = env->NewStringUTF(author.name().c_str()); - jstring key = env->NewStringUTF(author.sortKey().c_str()); - AndroidUtil::Method_Book_addAuthor->call(javaBook, javaString, key); - env->DeleteLocalRef(key); - env->DeleteLocalRef(javaString); + JString name(env, author.name(), false); + JString key(env, author.sortKey(), false); + AndroidUtil::Method_Book_addAuthor->call(javaBook, name.j(), key.j()); } const TagList &tags = book.tags(); @@ -99,18 +86,14 @@ static void fillMetaInfo(JNIEnv* env, jobject javaBook, Book &book) { } static void fillLanguageAndEncoding(JNIEnv* env, jobject javaBook, Book &book) { - jstring javaString; - - javaString = AndroidUtil::createJavaString(env, book.language()); - if (javaString != 0) { - AndroidUtil::Method_Book_setLanguage->call(javaBook, javaString); - env->DeleteLocalRef(javaString); + JString language(env, book.language()); + if (language.j() != 0) { + AndroidUtil::Method_Book_setLanguage->call(javaBook, language.j()); } - javaString = AndroidUtil::createJavaString(env, book.encoding()); - if (javaString != 0) { - AndroidUtil::Method_Book_setEncoding->call(javaBook, javaString); - env->DeleteLocalRef(javaString); + JString encoding(env, book.encoding()); + if (encoding.j() != 0) { + AndroidUtil::Method_Book_setEncoding->call(javaBook, encoding.j()); } } @@ -215,12 +198,10 @@ static bool initInternalHyperlinks(JNIEnv *env, jobject javaModel, BookModel &mo } allocator.flush(); - jstring linksDirectoryName = env->NewStringUTF(allocator.directoryName().c_str()); - jstring linksFileExtension = env->NewStringUTF(allocator.fileExtension().c_str()); + JString linksDirectoryName(env, allocator.directoryName(), false); + JString linksFileExtension(env, allocator.fileExtension(), false); jint linksBlocksNumber = allocator.blocksNumber(); - AndroidUtil::Method_NativeBookModel_initInternalHyperlinks->call(javaModel, linksDirectoryName, linksFileExtension, linksBlocksNumber); - env->DeleteLocalRef(linksDirectoryName); - env->DeleteLocalRef(linksFileExtension); + AndroidUtil::Method_NativeBookModel_initInternalHyperlinks->call(javaModel, linksDirectoryName.j(), linksFileExtension.j(), linksBlocksNumber); return !env->ExceptionCheck(); } @@ -265,10 +246,8 @@ static void initTOC(JNIEnv *env, jobject javaModel, const ContentsTree &tree) { const std::vector > &children = tree.children(); for (std::vector >::const_iterator it = children.begin(); it != children.end(); ++it) { const ContentsTree &child = **it; - jstring text = AndroidUtil::createJavaString(env, child.text()); - const int ref = child.reference(); - AndroidUtil::Method_NativeBookModel_addTOCItem->call(javaModel, text, ref); - env->DeleteLocalRef(text); + JString text(env, child.text()); + AndroidUtil::Method_NativeBookModel_addTOCItem->call(javaModel, text.j(), child.reference()); initTOC(env, javaModel, child); @@ -335,9 +314,8 @@ JNIEXPORT jint JNICALL Java_org_geometerplus_fbreader_formats_NativeFormatPlugin const std::vector &lst = *it; jobjectArray jList = env->NewObjectArray(lst.size(), AndroidUtil::Class_java_lang_String.j(), 0); for (std::size_t i = 0; i < lst.size(); ++i) { - jstring jString = AndroidUtil::createJavaString(env, lst[i]); - env->SetObjectArrayElement(jList, i, jString); - env->DeleteLocalRef(jString); + JString jString(env, lst[i]); + env->SetObjectArrayElement(jList, i, jString.j()); } AndroidUtil::Method_NativeBookModel_registerFontFamilyList->call(javaModel, jList); env->DeleteLocalRef(jList); @@ -348,21 +326,20 @@ JNIEXPORT jint JNICALL Java_org_geometerplus_fbreader_formats_NativeFormatPlugin if (it->second.isNull()) { continue; } - jstring family = AndroidUtil::createJavaString(env, it->first); + JString family(env, it->first); jstring normal = createJavaString(env, it->second->Normal); jstring bold = createJavaString(env, it->second->Bold); jstring italic = createJavaString(env, it->second->Italic); jstring boldItalic = createJavaString(env, it->second->BoldItalic); AndroidUtil::Method_NativeBookModel_registerFontEntry->call( - javaModel, family, normal, bold, italic, boldItalic + javaModel, family.j(), normal, bold, italic, boldItalic ); if (boldItalic != 0) env->DeleteLocalRef(boldItalic); if (italic != 0) env->DeleteLocalRef(italic); if (bold != 0) env->DeleteLocalRef(bold); if (normal != 0) env->DeleteLocalRef(normal); - env->DeleteLocalRef(family); } return 0; diff --git a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp index d009d18db..eab7068d1 100644 --- a/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp +++ b/jni/NativeFormats/fbreader/src/bookmodel/BookReader.cpp @@ -231,10 +231,9 @@ void BookReader::addImage(const std::string &id, shared_ptr image JNIEnv *env = AndroidUtil::getEnv(); jobject javaImage = AndroidUtil::createJavaImage(env, (const ZLFileImage&)*image); - jstring javaId = AndroidUtil::createJavaString(env, id); - AndroidUtil::Method_NativeBookModel_addImage->call(myModel.myJavaModel, javaId, javaImage); + JString javaId(env, id); + AndroidUtil::Method_NativeBookModel_addImage->call(myModel.myJavaModel, javaId.j(), javaImage); - env->DeleteLocalRef(javaId); env->DeleteLocalRef(javaImage); } diff --git a/jni/NativeFormats/util/AndroidUtil.cpp b/jni/NativeFormats/util/AndroidUtil.cpp index 9c5a0f3a2..8859578d1 100644 --- a/jni/NativeFormats/util/AndroidUtil.cpp +++ b/jni/NativeFormats/util/AndroidUtil.cpp @@ -218,10 +218,8 @@ bool AndroidUtil::init(JavaVM* jvm) { } jobject AndroidUtil::createJavaFile(JNIEnv *env, const std::string &path) { - jstring javaPath = createJavaString(env, path); - jobject javaFile = StaticMethod_ZLFile_createFileByPath->call(javaPath); - env->DeleteLocalRef(javaPath); - return javaFile; + JString javaPath(env, path, false); + return StaticMethod_ZLFile_createFileByPath->call(javaPath.j()); } jobject AndroidUtil::createJavaEncryptionInfo(JNIEnv *env, shared_ptr info) { @@ -229,25 +227,18 @@ jobject AndroidUtil::createJavaEncryptionInfo(JNIEnv *env, shared_ptrUri); - jstring method = createJavaString(env, info->Method); - jstring algorithm = createJavaString(env, info->Algorithm); - jstring contentId = createJavaString(env, info->ContentId); + JString uri(env, info->Uri, false); + JString method(env, info->Method, false); + JString algorithm(env, info->Algorithm, false); + JString contentId(env, info->ContentId, false); - jobject javaInfo = Constructor_FileEncryptionInfo->call(uri, method, algorithm, contentId); - - env->DeleteLocalRef(contentId); - env->DeleteLocalRef(algorithm); - env->DeleteLocalRef(method); - env->DeleteLocalRef(uri); - - return javaInfo; + return Constructor_FileEncryptionInfo->call(uri.j(), method.j(), algorithm.j(), contentId.j()); } jobject AndroidUtil::createJavaImage(JNIEnv *env, const ZLFileImage &image) { - jstring javaMimeType = createJavaString(env, image.mimeType()); + JString javaMimeType(env, image.mimeType()); jobject javaFile = createJavaFile(env, image.file().path()); - jstring javaEncoding = createJavaString(env, image.encoding()); + JString javaEncoding(env, image.encoding()); std::vector offsets, sizes; const ZLFileImage::Blocks &blocks = image.blocks(); @@ -261,7 +252,7 @@ jobject AndroidUtil::createJavaImage(JNIEnv *env, const ZLFileImage &image) { jobject javaEncryptionInfo = createJavaEncryptionInfo(env, image.encryptionInfo()); jobject javaImage = Constructor_ZLFileImage->call( - javaMimeType, javaFile, javaEncoding, + javaMimeType.j(), javaFile, javaEncoding.j(), javaOffsets, javaSizes, javaEncryptionInfo ); @@ -269,9 +260,7 @@ jobject AndroidUtil::createJavaImage(JNIEnv *env, const ZLFileImage &image) { env->DeleteLocalRef(javaEncryptionInfo); } - env->DeleteLocalRef(javaEncoding); env->DeleteLocalRef(javaFile); - env->DeleteLocalRef(javaMimeType); env->DeleteLocalRef(javaOffsets); env->DeleteLocalRef(javaSizes); @@ -288,8 +277,14 @@ std::string AndroidUtil::fromJavaString(JNIEnv *env, jstring from) { return result; } -jstring AndroidUtil::createJavaString(JNIEnv* env, shared_ptr str) { - return str.isNull() ? 0 : createJavaString(env, *str); +JString::JString(JNIEnv* env, const std::string &str, bool emptyIsNull) : myEnv(env) { + myJ = (emptyIsNull && str.empty()) ? 0 : env->NewStringUTF(str.c_str()); +} + +JString::~JString() { + if (myJ != 0) { + myEnv->DeleteLocalRef(myJ); + } } jstring AndroidUtil::createJavaString(JNIEnv* env, const std::string &str) { diff --git a/jni/NativeFormats/util/AndroidUtil.h b/jni/NativeFormats/util/AndroidUtil.h index 4b4e306b2..a056a1967 100644 --- a/jni/NativeFormats/util/AndroidUtil.h +++ b/jni/NativeFormats/util/AndroidUtil.h @@ -44,6 +44,22 @@ class ZLFile; class FileEncryptionInfo; class ZLFileImage; +class JString { + +public: + JString(JNIEnv* env, const std::string &str, bool emptyIsNull = true); + jstring j(); + ~JString(); + +private: + JNIEnv *myEnv; + jstring myJ; + +private: + JString(const JString&); + const JString& operator = (const JString&); +}; + class AndroidUtil { private: @@ -155,7 +171,6 @@ public: static JNIEnv *getEnv(); static std::string fromJavaString(JNIEnv *env, jstring from); - static jstring createJavaString(JNIEnv* env, shared_ptr); static jstring createJavaString(JNIEnv* env, const std::string &str); static std::string convertNonUtfString(const std::string &str); @@ -171,4 +186,6 @@ public: //static void throwBookReadingException(const std::string &resourceId, const ZLFile &file); }; +inline jstring JString::j() { return myJ; } + #endif /* __ANDROIDUTIL_H__ */