1 #include <jni.h>
2 #include <nativehelper/scoped_utf_chars.h>
3 
4 #include "leveldb/db.h"
5 
6 #ifndef _Included_com_android_providers_media_leveldb_LevelDBInstance
7 #define _Included_com_android_providers_media_leveldb_LevelDBInstance
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 #undef com_android_providers_media_leveldb_LevelDBInstance_MAX_BULK_INSERT_ENTRIES
12 #define com_android_providers_media_leveldb_LevelDBInstance_MAX_BULK_INSERT_ENTRIES 100L
13 
getStatusCode(leveldb::Status status)14 static std::string getStatusCode(leveldb::Status status) {
15     if (status.ok()) {
16         return "0";
17     } else if (status.IsNotFound()) {
18         return "1";
19     } else if (status.IsInvalidArgument()) {
20         return "2";
21     } else {
22         return "3";
23     }
24 }
25 
createLevelDBResult(JNIEnv * env,leveldb::Status status,std::string value)26 static jobject createLevelDBResult(JNIEnv* env, leveldb::Status status, std::string value) {
27     // Create the object of the class LevelDBResult
28     jclass levelDbResultClass = env->FindClass("com/android/providers/media/leveldb/LevelDBResult");
29     jobject levelDbResultData = env->AllocObject(levelDbResultClass);
30 
31     // Get the UserData fields to be set
32     jfieldID codeField = env->GetFieldID(levelDbResultClass, "mCode", "Ljava/lang/String;");
33     jfieldID messageField =
34             env->GetFieldID(levelDbResultClass, "mErrorMessage", "Ljava/lang/String;");
35     jfieldID valueField = env->GetFieldID(levelDbResultClass, "mValue", "Ljava/lang/String;");
36 
37     std::string statusCode = getStatusCode(status);
38     env->SetObjectField(levelDbResultData, codeField, env->NewStringUTF(statusCode.c_str()));
39     env->SetObjectField(levelDbResultData, messageField,
40                         env->NewStringUTF(status.ToString().c_str()));
41     env->SetObjectField(levelDbResultData, valueField, env->NewStringUTF(value.c_str()));
42     return levelDbResultData;
43 }
44 
insertInLevelDB(JNIEnv * env,jobject obj,jlong leveldbptr,jobject leveldbentry)45 static leveldb::Status insertInLevelDB(JNIEnv* env, jobject obj, jlong leveldbptr,
46                                        jobject leveldbentry) {
47     jclass levelDbEntryClass = env->GetObjectClass(leveldbentry);
48     jmethodID getKeyMethodId =
49             env->GetMethodID(levelDbEntryClass, "getKey", "()Ljava/lang/String;");
50     jmethodID getValueMethodId =
51             env->GetMethodID(levelDbEntryClass, "getValue", "()Ljava/lang/String;");
52 
53     jstring key = (jstring)env->CallObjectMethod(leveldbentry, getKeyMethodId);
54     jstring value = (jstring)env->CallObjectMethod(leveldbentry, getValueMethodId);
55     ScopedUtfChars utf_chars_key(env, key);
56     ScopedUtfChars utf_chars_value(env, value);
57     leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
58     leveldb::Status status;
59     status = leveldb->Put(leveldb::WriteOptions(), utf_chars_key.c_str(), utf_chars_value.c_str());
60     return status;
61 }
62 
insert(JNIEnv * env,jobject obj,jlong leveldbptr,jobject leveldbentry)63 static jobject insert(JNIEnv* env, jobject obj, jlong leveldbptr, jobject leveldbentry) {
64     return createLevelDBResult(env, insertInLevelDB(env, obj, leveldbptr, leveldbentry), "");
65 }
66 
67 /*
68  * Class:     com_android_providers_media_leveldb_LevelDBInstance
69  * Method:    nativeCreateInstance
70  * Signature: (Ljava/lang/String;)J
71  */
72 JNIEXPORT jlong JNICALL
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeCreateInstance(JNIEnv * env,jclass leveldbInstanceClass,jstring path)73             Java_com_android_providers_media_leveldb_LevelDBInstance_nativeCreateInstance(
74                 JNIEnv* env, jclass leveldbInstanceClass, jstring path) {
75     ScopedUtfChars utf_chars_path(env, path);
76     leveldb::Options options;
77     options.create_if_missing = true;
78     leveldb::DB* leveldb;
79     leveldb::Status status = leveldb::DB::Open(options, utf_chars_path.c_str(), &leveldb);
80     if (status.ok()) {
81         return reinterpret_cast<jlong>(leveldb);
82     } else {
83         long val = 0;
84         return (jlong)val;
85     }
86 }
87 
88 /*
89  * Class:     com_android_providers_media_leveldb_LevelDBInstance
90  * Method:    nativeQuery
91  * Signature: (JLjava/lang/String;)Lcom/android/providers/media/leveldb/LevelDBResult;
92  */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeQuery(JNIEnv * env,jobject obj,jlong leveldbptr,jstring path)93 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeQuery(
94         JNIEnv* env, jobject obj, jlong leveldbptr, jstring path) {
95     ScopedUtfChars utf_chars_path(env, path);
96     leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
97     leveldb::Status status;
98     std::string value = "";
99     status = leveldb->Get(leveldb::ReadOptions(), utf_chars_path.c_str(), &value);
100     return createLevelDBResult(env, status, value);
101 }
102 
103 /*
104  * Class:     com_android_providers_media_leveldb_LevelDBInstance
105  * Method:    nativeInsert
106  * Signature: (JLcom/android/providers/media/leveldb/LevelDBEntry;)
107  *                   Lcom/android/providers/media/leveldb/LevelDBResult;
108  */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeInsert(JNIEnv * env,jobject obj,jlong leveldbptr,jobject leveldbentry)109 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeInsert(
110         JNIEnv* env, jobject obj, jlong leveldbptr, jobject leveldbentry) {
111     return insert(env, obj, leveldbptr, leveldbentry);
112 }
113 
114 /*
115  * Class:     com_android_providers_media_leveldb_LevelDBInstance
116  * Method:    nativeBulkInsert
117  * Signature: (JLjava/util/List;)Lcom/android/providers/media/leveldb/LevelDBResult;
118  */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeBulkInsert(JNIEnv * env,jobject obj,jlong leveldbptr,jobject entries)119 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeBulkInsert(
120         JNIEnv* env, jobject obj, jlong leveldbptr, jobject entries) {
121     // Get the class of the list
122     jclass listClass = env->GetObjectClass(entries);
123 
124     // Get the iterator method ID
125     jmethodID iteratorMethod = env->GetMethodID(listClass, "iterator", "()Ljava/util/Iterator;");
126 
127     // Get the iterator object
128     jobject iterator = env->CallObjectMethod(entries, iteratorMethod);
129 
130     // Get the iterator class
131     jclass iteratorClass = env->GetObjectClass(iterator);
132 
133     // Get the hasNext and next method IDs
134     jmethodID hasNextMethod = env->GetMethodID(iteratorClass, "hasNext", "()Z");
135     jmethodID nextMethod = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
136 
137     leveldb::Status status;
138 
139     // Iterate through the list
140     while (env->CallBooleanMethod(iterator, hasNextMethod)) {
141         jobject jLevelDBEntryObject = env->CallObjectMethod(iterator, nextMethod);
142         leveldb::Status status = insertInLevelDB(env, obj, leveldbptr, jLevelDBEntryObject);
143         if (!status.ok()) {
144             break;
145         }
146     }
147 
148     return createLevelDBResult(env, status, "");
149 }
150 
151 /*
152  * Class:     com_android_providers_media_leveldb_LevelDBInstance
153  * Method:    nativeDelete
154  * Signature: (JLjava/lang/String;)Lcom/android/providers/media/leveldb/LevelDBResult;
155  */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeDelete(JNIEnv * env,jobject obj,jlong leveldbptr,jstring key)156 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeDelete(
157         JNIEnv* env, jobject obj, jlong leveldbptr, jstring key) {
158     ScopedUtfChars utf_chars_key(env, key);
159     leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
160     leveldb::Status status;
161     status = leveldb->Delete(leveldb::WriteOptions(), utf_chars_key.c_str());
162     return createLevelDBResult(env, status, "");
163 }
164 
165 #ifdef __cplusplus
166 }
167 #endif
168 #endif
169