From 2ddf4e5a0176051a0e39ed13a126b6557c692da5 Mon Sep 17 00:00:00 2001 From: Nikolay Pultsin Date: Sat, 31 Mar 2012 02:17:25 +0100 Subject: [PATCH] JavaType as a return type for methods --- jni/NativeFormats/util/AndroidUtil.cpp | 52 ++++++++++++++------------ jni/NativeFormats/util/AndroidUtil.h | 2 + jni/NativeFormats/util/JniEnvelope.cpp | 41 ++++++++++++++------ jni/NativeFormats/util/JniEnvelope.h | 48 +++++++++++++++++------- 4 files changed, 94 insertions(+), 49 deletions(-) diff --git a/jni/NativeFormats/util/AndroidUtil.cpp b/jni/NativeFormats/util/AndroidUtil.cpp index 6a5fdb6cb..20d400bd3 100644 --- a/jni/NativeFormats/util/AndroidUtil.cpp +++ b/jni/NativeFormats/util/AndroidUtil.cpp @@ -28,6 +28,7 @@ JavaVM *AndroidUtil::ourJavaVM = 0; shared_ptr AndroidUtil::Class_java_lang_RuntimeException; shared_ptr AndroidUtil::Class_java_lang_String; shared_ptr AndroidUtil::Class_java_util_Collection; +shared_ptr AndroidUtil::Class_java_util_List; shared_ptr AndroidUtil::Class_java_util_Locale; shared_ptr AndroidUtil::Class_java_io_InputStream; shared_ptr AndroidUtil::Class_ZLibrary; @@ -39,6 +40,7 @@ shared_ptr AndroidUtil::Class_JavaEncodingCollection; shared_ptr AndroidUtil::Class_Paths; shared_ptr AndroidUtil::Class_ZLFile; shared_ptr AndroidUtil::Class_ZLFileImage; +shared_ptr AndroidUtil::Class_ZLTextModel; shared_ptr AndroidUtil::Class_Book; shared_ptr AndroidUtil::Class_Tag; shared_ptr AndroidUtil::Class_NativeBookModel; @@ -125,64 +127,70 @@ bool AndroidUtil::init(JavaVM* jvm) { JNIEnv *env = getEnv(); Class_java_lang_RuntimeException = new JavaClass(env, "java/lang/RuntimeException"); - Class_java_lang_String = new JavaClass(env, "java/lang/String"); + Class_java_util_Collection = new JavaClass(env, "java/util/Collection"); + Class_java_util_List = new JavaClass(env, "java/util/List"); + Class_java_util_Locale = new JavaClass(env, "java/util/Locale"); + Class_java_io_InputStream = new JavaClass(env, "java/io/InputStream"); + + Class_ZLibrary = new JavaClass(env, "org/geometerplus/zlibrary/core/library/ZLibrary"); + Class_ZLFile = new JavaClass(env, "org/geometerplus/zlibrary/core/filesystem/ZLFile"); + Class_ZLFileImage = new JavaClass(env, "org/geometerplus/zlibrary/core/image/ZLFileImage"); + Class_ZLTextModel = new JavaClass(env, "org/geometerplus/zlibrary/text/model/ZLTextModel"); + + Class_Encoding = new JavaClass(env, "org/geometerplus/zlibrary/core/encodings/Encoding"); + Class_EncodingConverter = new JavaClass(env, "org/geometerplus/zlibrary/core/encodings/EncodingConverter"); + Class_JavaEncodingCollection = new JavaClass(env, "org/geometerplus/zlibrary/core/encodings/JavaEncodingCollection"); + + Class_NativeFormatPlugin = new JavaClass(env, "org/geometerplus/fbreader/formats/NativeFormatPlugin"); + Class_PluginCollection = new JavaClass(env, "org/geometerplus/fbreader/formats/PluginCollection"); + Class_Paths = new JavaClass(env, "org/geometerplus/fbreader/Paths"); + Class_Book = new JavaClass(env, "org/geometerplus/fbreader/library/Book"); + Class_Tag = new JavaClass(env, "org/geometerplus/fbreader/library/Tag"); + Class_NativeBookModel = new JavaClass(env, "org/geometerplus/fbreader/bookmodel/NativeBookModel"); + Method_java_lang_String_toLowerCase = new StringMethod(*Class_java_lang_String, "toLowerCase", "()"); Method_java_lang_String_toUpperCase = new StringMethod(*Class_java_lang_String, "toUpperCase", "()"); - Class_java_util_Collection = new JavaClass(env, "java/util/Collection"); CHECK_NULL( MID_java_util_Collection_toArray = env->GetMethodID(Class_java_util_Collection->j(), "toArray", "()[Ljava/lang/Object;") ); - Class_java_util_Locale = new JavaClass(env, "java/util/Locale"); StaticMethod_java_util_Locale_getDefault = new StaticObjectMethod(*Class_java_util_Locale, "getDefault", *Class_java_util_Locale, "()"); Method_java_util_Locale_getLanguage = new StringMethod(*Class_java_util_Locale, "getLanguage", "()"); - Class_java_io_InputStream = new JavaClass(env, "java/io/InputStream"); Method_java_io_InputStream_close = new VoidMethod(*Class_java_io_InputStream, "close", "()"); Method_java_io_InputStream_read = new IntMethod(*Class_java_io_InputStream, "read", "([BII)"); Method_java_io_InputStream_skip = new LongMethod(*Class_java_io_InputStream, "skip", "(J)"); - Class_ZLibrary = new JavaClass(env, "org/geometerplus/zlibrary/core/library/ZLibrary"); StaticMethod_ZLibrary_Instance = new StaticObjectMethod(*Class_ZLibrary, "Instance", *Class_ZLibrary, "()"); Method_ZLibrary_getVersionName = new StringMethod(*Class_ZLibrary, "getVersionName", "()"); - Class_NativeFormatPlugin = new JavaClass(env, "org/geometerplus/fbreader/formats/NativeFormatPlugin"); Constructor_NativeFormatPlugin = new Constructor(*Class_NativeFormatPlugin, "(Ljava/lang/String;)V"); Method_NativeFormatPlugin_supportedFileType = new StringMethod(*Class_NativeFormatPlugin, "supportedFileType", "()"); - Class_PluginCollection = new JavaClass(env, "org/geometerplus/fbreader/formats/PluginCollection"); StaticMethod_PluginCollection_Instance = new StaticObjectMethod(*Class_PluginCollection, "Instance", *Class_PluginCollection, "()"); - Class_Encoding = new JavaClass(env, "org/geometerplus/zlibrary/core/encodings/Encoding"); - Method_Encoding_createConverter = new ObjectMethod(*Class_Encoding, "createConverter", "org/geometerplus/zlibrary/core/encodings/EncodingConverter", "()"); - - Class_EncodingConverter = new JavaClass(env, "org/geometerplus/zlibrary/core/encodings/EncodingConverter"); + Method_Encoding_createConverter = new ObjectMethod(*Class_Encoding, "createConverter", *Class_EncodingConverter, "()"); Field_EncodingConverter_Name = new ObjectField(*Class_EncodingConverter, "Name", *Class_java_lang_String); Method_EncodingConverter_convert = new IntMethod(*Class_EncodingConverter, "convert", "([BII[BI)"); Method_EncodingConverter_reset = new VoidMethod(*Class_EncodingConverter, "reset", "()"); - Class_JavaEncodingCollection = new JavaClass(env, "org/geometerplus/zlibrary/core/encodings/JavaEncodingCollection"); StaticMethod_JavaEncodingCollection_Instance = new StaticObjectMethod(*Class_JavaEncodingCollection, "Instance", *Class_JavaEncodingCollection, "()"); - Method_JavaEncodingCollection_getEncoding_String = new ObjectMethod(*Class_JavaEncodingCollection, "getEncoding", "org/geometerplus/zlibrary/core/encodings/Encoding", "(Ljava/lang/String;)"); - Method_JavaEncodingCollection_getEncoding_int = new ObjectMethod(*Class_JavaEncodingCollection, "getEncoding", "org/geometerplus/zlibrary/core/encodings/Encoding", "(I)"); + Method_JavaEncodingCollection_getEncoding_String = new ObjectMethod(*Class_JavaEncodingCollection, "getEncoding", *Class_Encoding, "(Ljava/lang/String;)"); + Method_JavaEncodingCollection_getEncoding_int = new ObjectMethod(*Class_JavaEncodingCollection, "getEncoding", *Class_Encoding, "(I)"); Method_JavaEncodingCollection_providesConverterFor = new BooleanMethod(*Class_JavaEncodingCollection, "providesConverterFor", "(Ljava/lang/String;)"); - Class_ZLFile = new JavaClass(env, "org/geometerplus/zlibrary/core/filesystem/ZLFile"); StaticMethod_ZLFile_createFileByPath = new StaticObjectMethod(*Class_ZLFile, "createFileByPath", *Class_ZLFile, "(Ljava/lang/String;)"); - Method_ZLFile_children = new ObjectMethod(*Class_ZLFile, "children", "java/util/List", "()"); + Method_ZLFile_children = new ObjectMethod(*Class_ZLFile, "children", *Class_java_util_List, "()"); Method_ZLFile_exists = new BooleanMethod(*Class_ZLFile, "exists", "()"); Method_ZLFile_isDirectory = new BooleanMethod(*Class_ZLFile, "isDirectory", "()"); - Method_ZLFile_getInputStream = new ObjectMethod(*Class_ZLFile, "getInputStream", "java/io/InputStream", "()"); + Method_ZLFile_getInputStream = new ObjectMethod(*Class_ZLFile, "getInputStream", *Class_java_io_InputStream, "()"); Method_ZLFile_getPath = new StringMethod(*Class_ZLFile, "getPath", "()"); Method_ZLFile_size = new LongMethod(*Class_ZLFile, "size", "()"); - Class_ZLFileImage = new JavaClass(env, "org/geometerplus/zlibrary/core/image/ZLFileImage"); Constructor_ZLFileImage = new Constructor(*Class_ZLFileImage, "(Ljava/lang/String;Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;Ljava/lang/String;II)V"); - Class_Paths = new JavaClass(env, "org/geometerplus/fbreader/Paths"); StaticMethod_Paths_cacheDirectory = new StaticObjectMethod(*Class_Paths, "cacheDirectory", *Class_java_lang_String, "()"); - Class_Book = new JavaClass(env, "org/geometerplus/fbreader/library/Book"); Field_Book_File = new ObjectField(*Class_Book, "File", *Class_ZLFile); Method_Book_getTitle = new StringMethod(*Class_Book, "getTitle", "()"); Method_Book_getLanguage = new StringMethod(*Class_Book, "getLanguage", "()"); @@ -195,14 +203,12 @@ bool AndroidUtil::init(JavaVM* jvm) { Method_Book_addTag = new VoidMethod(*Class_Book, "addTag", "(Lorg/geometerplus/fbreader/library/Tag;)"); Method_Book_save = new BooleanMethod(*Class_Book, "save", "()"); - Class_Tag = new JavaClass(env, "org/geometerplus/fbreader/library/Tag"); StaticMethod_Tag_getTag = new StaticObjectMethod(*Class_Tag, "getTag", *Class_Tag, "(Lorg/geometerplus/fbreader/library/Tag;Ljava/lang/String;)"); - Class_NativeBookModel = new JavaClass(env, "org/geometerplus/fbreader/bookmodel/NativeBookModel"); Field_NativeBookModel_Book = new ObjectField(*Class_NativeBookModel, "Book", *Class_Book); Method_NativeBookModel_initInternalHyperlinks = new VoidMethod(*Class_NativeBookModel, "initInternalHyperlinks", "(Ljava/lang/String;Ljava/lang/String;I)"); Method_NativeBookModel_initTOC = new VoidMethod(*Class_NativeBookModel, "initTOC", "(Lorg/geometerplus/zlibrary/text/model/ZLTextModel;[I[I)"); - Method_NativeBookModel_createTextModel = new ObjectMethod(*Class_NativeBookModel, "createTextModel", "org/geometerplus/zlibrary/text/model/ZLTextModel", "(Ljava/lang/String;Ljava/lang/String;I[I[I[I[I[BLjava/lang/String;Ljava/lang/String;I)"); + Method_NativeBookModel_createTextModel = new ObjectMethod(*Class_NativeBookModel, "createTextModel", *Class_ZLTextModel, "(Ljava/lang/String;Ljava/lang/String;I[I[I[I[I[BLjava/lang/String;Ljava/lang/String;I)"); Method_NativeBookModel_setBookTextModel = new VoidMethod(*Class_NativeBookModel, "setBookTextModel", "(Lorg/geometerplus/zlibrary/text/model/ZLTextModel;)"); Method_NativeBookModel_setFootnoteModel = new VoidMethod(*Class_NativeBookModel, "setFootnoteModel", "(Lorg/geometerplus/zlibrary/text/model/ZLTextModel;)"); Method_NativeBookModel_addImage = new VoidMethod(*Class_NativeBookModel, "addImage", "(Ljava/lang/String;Lorg/geometerplus/zlibrary/core/image/ZLImage;)"); diff --git a/jni/NativeFormats/util/AndroidUtil.h b/jni/NativeFormats/util/AndroidUtil.h index 9d3c6b063..5ee6e70ce 100644 --- a/jni/NativeFormats/util/AndroidUtil.h +++ b/jni/NativeFormats/util/AndroidUtil.h @@ -50,11 +50,13 @@ public: static shared_ptr Class_java_lang_RuntimeException; static shared_ptr Class_java_lang_String; static shared_ptr Class_java_util_Collection; + static shared_ptr Class_java_util_List; static shared_ptr Class_java_util_Locale; static shared_ptr Class_java_io_InputStream; static shared_ptr Class_ZLibrary; static shared_ptr Class_ZLFile; static shared_ptr Class_ZLFileImage; + static shared_ptr Class_ZLTextModel; static shared_ptr Class_NativeFormatPlugin; static shared_ptr Class_PluginCollection; static shared_ptr Class_Encoding; diff --git a/jni/NativeFormats/util/JniEnvelope.cpp b/jni/NativeFormats/util/JniEnvelope.cpp index 390900e33..8b1f9804b 100644 --- a/jni/NativeFormats/util/JniEnvelope.cpp +++ b/jni/NativeFormats/util/JniEnvelope.cpp @@ -23,6 +23,11 @@ static const std::string JNI_LOGGER_CLASS = "JniLog"; +const JavaPrimitiveType JavaPrimitiveType::Void("V"); +const JavaPrimitiveType JavaPrimitiveType::Int("I"); +const JavaPrimitiveType JavaPrimitiveType::Long("J"); +const JavaPrimitiveType JavaPrimitiveType::Boolean("Z"); + JavaType::JavaType() { } @@ -30,19 +35,28 @@ JavaType::~JavaType() { } JavaClass::JavaClass(JNIEnv *env, const std::string &name) : myName(name), myEnv(env) { - jclass ref = env->FindClass(name.c_str()); - myClass = (jclass)env->NewGlobalRef(ref); - env->DeleteLocalRef(ref); + myClass = 0; } JavaClass::~JavaClass() { - myEnv->DeleteGlobalRef(myClass); + if (myClass != 0) { + myEnv->DeleteGlobalRef(myClass); + } } std::string JavaClass::code() const { return "L" + myName + ";"; } +jclass JavaClass::j() const { + if (myClass == 0) { + jclass ref = myEnv->FindClass(myName.c_str()); + myClass = (jclass)myEnv->NewGlobalRef(ref); + myEnv->DeleteLocalRef(ref); + } + return myClass; +} + Member::Member(const JavaClass &cls) : myClass(cls) { //ZLLogger::Instance().registerClass(JNI_LOGGER_CLASS); } @@ -69,8 +83,9 @@ Field::Field(const JavaClass &cls, const std::string &name, const JavaType &type Field::~Field() { } -Method::Method(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Member(cls), myName(name) { - myId = env().GetMethodID(jClass(), name.c_str(), parameters.c_str()); +Method::Method(const JavaClass &cls, const std::string &name, const JavaType &returnType, const std::string ¶meters) : Member(cls), myName(name) { + const std::string signature = parameters + returnType.code(); + myId = env().GetMethodID(jClass(), name.c_str(), signature.c_str()); } Method::~Method() { @@ -94,7 +109,7 @@ jobject ObjectField::value(jobject obj) const { return val; } -VoidMethod::VoidMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, parameters + "V") { +VoidMethod::VoidMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, JavaPrimitiveType::Void, parameters) { } void VoidMethod::call(jobject base, ...) { @@ -106,7 +121,7 @@ void VoidMethod::call(jobject base, ...) { ZLLogger::Instance().println(JNI_LOGGER_CLASS, "finished VoidMethod " + myName); } -IntMethod::IntMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, parameters + "I") { +IntMethod::IntMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, JavaPrimitiveType::Int, parameters) { } jint IntMethod::call(jobject base, ...) { @@ -119,7 +134,7 @@ jint IntMethod::call(jobject base, ...) { return result; } -LongMethod::LongMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, parameters + "J") { +LongMethod::LongMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, JavaPrimitiveType::Long, parameters) { } jlong LongMethod::call(jobject base, ...) { @@ -132,7 +147,7 @@ jlong LongMethod::call(jobject base, ...) { return result; } -BooleanMethod::BooleanMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, parameters + "Z") { +BooleanMethod::BooleanMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, JavaPrimitiveType::Boolean, parameters) { } jboolean BooleanMethod::call(jobject base, ...) { @@ -145,7 +160,9 @@ jboolean BooleanMethod::call(jobject base, ...) { return result; } -StringMethod::StringMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, parameters + "Ljava/lang/String;") { +static JavaPrimitiveType FakeString("Ljava/lang/String;"); + +StringMethod::StringMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters) : Method(cls, name, FakeString, parameters) { } jstring StringMethod::call(jobject base, ...) { @@ -158,7 +175,7 @@ jstring StringMethod::call(jobject base, ...) { return result; } -ObjectMethod::ObjectMethod(const JavaClass &cls, const std::string &name, const std::string &returnType, const std::string ¶meters) : Method(cls, name, parameters + "L" + returnType + ";") { +ObjectMethod::ObjectMethod(const JavaClass &cls, const std::string &name, const JavaType &returnType, const std::string ¶meters) : Method(cls, name, returnType, parameters) { } jobject ObjectMethod::call(jobject base, ...) { diff --git a/jni/NativeFormats/util/JniEnvelope.h b/jni/NativeFormats/util/JniEnvelope.h index 226526e7f..e2f30afec 100644 --- a/jni/NativeFormats/util/JniEnvelope.h +++ b/jni/NativeFormats/util/JniEnvelope.h @@ -38,6 +38,25 @@ private: const JavaType &operator = (const JavaType&); }; +class JavaPrimitiveType : public JavaType { + +public: + static const JavaPrimitiveType Void; + static const JavaPrimitiveType Int; + static const JavaPrimitiveType Long; + static const JavaPrimitiveType Boolean; + +//protected: +public: + JavaPrimitiveType(const std::string &code); + +public: + std::string code() const; + +private: + const std::string myCode; +}; + class JavaClass : public JavaType { public: @@ -49,7 +68,7 @@ public: private: const std::string myName; JNIEnv *myEnv; - jclass myClass; + mutable jclass myClass; friend class Member; }; @@ -75,7 +94,7 @@ private: class Constructor : public Member { public: - Constructor(const JavaClass &cls, const std::string &signature); + Constructor(const JavaClass &cls, const std::string ¶meters); jobject call(...); private: @@ -96,7 +115,7 @@ protected: class Method : public Member { public: - Method(const JavaClass &cls, const std::string &name, const std::string &signature); + Method(const JavaClass &cls, const std::string &name, const JavaType &type, const std::string ¶meters); virtual ~Method(); protected: @@ -107,7 +126,7 @@ protected: class StaticMethod : public Member { public: - StaticMethod(const JavaClass &cls, const std::string &name, const JavaType &returnType, const std::string &signature); + StaticMethod(const JavaClass &cls, const std::string &name, const JavaType &returnType, const std::string ¶meters); virtual ~StaticMethod(); protected: @@ -125,55 +144,56 @@ public: class VoidMethod : public Method { public: - VoidMethod(const JavaClass &cls, const std::string &name, const std::string &signature); + VoidMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters); void call(jobject base, ...); }; class IntMethod : public Method { public: - IntMethod(const JavaClass &cls, const std::string &name, const std::string &signature); + IntMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters); jint call(jobject base, ...); }; class LongMethod : public Method { public: - LongMethod(const JavaClass &cls, const std::string &name, const std::string &signature); + LongMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters); jlong call(jobject base, ...); }; class BooleanMethod : public Method { public: - BooleanMethod(const JavaClass &cls, const std::string &name, const std::string &signature); + BooleanMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters); jboolean call(jobject base, ...); }; class StringMethod : public Method { public: - StringMethod(const JavaClass &cls, const std::string &name, const std::string &signature); + StringMethod(const JavaClass &cls, const std::string &name, const std::string ¶meters); jstring call(jobject base, ...); }; class ObjectMethod : public Method { public: - ObjectMethod(const JavaClass &cls, const std::string &name, const std::string &returnType, const std::string &signature); + ObjectMethod(const JavaClass &cls, const std::string &name, const JavaType &returnType, const std::string ¶meters); jobject call(jobject base, ...); }; class StaticObjectMethod : public StaticMethod { public: - StaticObjectMethod(const JavaClass &cls, const std::string &name, const JavaType &returnType, const std::string &signature); + StaticObjectMethod(const JavaClass &cls, const std::string &name, const JavaType &returnType, const std::string ¶meters); jobject call(...); }; -inline jclass JavaClass::j() const { return myClass; } - inline JNIEnv &Member::env() const { return *myClass.myEnv; } -inline jclass Member::jClass() const { return myClass.myClass; } +inline jclass Member::jClass() const { return myClass.j(); } + +inline JavaPrimitiveType::JavaPrimitiveType(const std::string &code) : myCode(code) {} +inline std::string JavaPrimitiveType::code() const { return myCode; } #endif /* __JNIENVELOPE_H__ */