1 /******************************************************************************
2 *
3 * swordstub.cpp - JNI bindings
4 *
5 * $Id: swordstub.cpp 3524 2017-11-07 03:08:49Z scribe $
6 *
7 * Copyright 2009-2013 CrossWire Bible Society (http://www.crosswire.org)
8 * CrossWire Bible Society
9 * P. O. Box 2528
10 * Tempe, AZ 85280-2528
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation version 2.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 */
22
23 #include <iostream>
24 #include <vector>
25 #include <map>
26
27 #include <jni.h>
28 #include <android/log.h>
29
30 #include <utilstr.h>
31 #include <swversion.h>
32 #include <swmgr.h>
33 #include <swlog.h>
34 #include <filemgr.h>
35 #include <swmodule.h>
36 #include <versekey.h>
37 #include <localemgr.h>
38 #include <treekeyidx.h>
39 #include <installmgr.h>
40 #include <remotetrans.h>
41 #include <rtfhtml.h>
42 //#include <android/native_activity.h>
43
44
45 #ifdef BIBLESYNC
46 #include <biblesync.hh>
47 #endif
48
49 #include "webmgr.hpp"
50 #include "org_crosswire_android_sword_SWMgr.h"
51 #include "org_crosswire_android_sword_SWModule.h"
52 #include "org_crosswire_android_sword_InstallMgr.h"
53
54
55 using std::cerr;
56 using std::map;
57 using std::vector;
58
59 using namespace sword;
60
61 namespace {
62 WebMgr *mgr = 0;
63 InstallMgr *installMgr = 0;
64
65 #ifdef BIBLESYNC
66 BibleSync *bibleSync = 0;
67 using std::string;
68 jobject bibleSyncListener = 0;
69 JNIEnv *bibleSyncListenerEnv = 0;
70 #endif
71 static SWBuf STORAGE_BASE;
72 static char *SWORD_PATH = "/sdcard/sword";
73 static char *AND_BIBLE_MODULES_PATH = "/sdcard/Android/data/net.bible.android.activity/files";
74 //ANativeActivity *_activity;
75
76 class InstallStatusReporter : public StatusReporter {
77 public:
78 JNIEnv *env;
79 jobject callback;
80 unsigned long last;
81
InstallStatusReporter()82 InstallStatusReporter() : env(0), callback(0), last(0) {
83 }
84
init(JNIEnv * env,jobject callback)85 void init(JNIEnv *env, jobject callback) {
86 this->env = env;
87 this->callback = callback;
88 last = 0xffffffff;
89 }
90
update(unsigned long totalBytes,unsigned long completedBytes)91 virtual void update(unsigned long totalBytes, unsigned long completedBytes) {
92
93 // assert we have a callback
94 if (!callback) return;
95
96 if (completedBytes != last) {
97 last = completedBytes;
98 jclass cls = env->GetObjectClass(callback);
99 jmethodID mid = env->GetMethodID(cls, "update", "(JJ)V");
100 if (mid != 0) {
101 env->CallVoidMethod(callback, mid, (jlong)totalBytes, (jlong)completedBytes);
102 }
103 env->DeleteLocalRef(cls);
104 }
105 }
106
preStatus(long totalBytes,long completedBytes,const char * message)107 virtual void preStatus(long totalBytes, long completedBytes, const char *message) {
108
109 // assert we have a callback
110 if (!callback) return;
111
112 jclass cls = env->GetObjectClass(callback);
113 jmethodID mid = env->GetMethodID(cls, "preStatus", "(JJLjava/lang/String;)V");
114 if (mid != 0) {
115 jstring msg = env->NewStringUTF(assureValidUTF8((const char *)message));
116 env->CallVoidMethod(callback, mid, (jlong)totalBytes, (jlong)completedBytes, msg);
117 env->DeleteLocalRef(msg);
118 }
119 env->DeleteLocalRef(cls);
120 }
121 } *installStatusReporter = 0;
122 bool disclaimerConfirmed = false;
123
124 class AndroidLogger : public SWLog {
125 vector<int> levelMapping;
126 public:
AndroidLogger()127 AndroidLogger() {
128 levelMapping.resize(10, 0);
129 levelMapping[SWLog::LOG_ERROR] = ANDROID_LOG_ERROR;
130 levelMapping[SWLog::LOG_WARN] = ANDROID_LOG_WARN;
131 levelMapping[SWLog::LOG_INFO] = ANDROID_LOG_INFO;
132 levelMapping[SWLog::LOG_TIMEDINFO] = ANDROID_LOG_INFO;
133 levelMapping[SWLog::LOG_DEBUG] = ANDROID_LOG_DEBUG;
134 }
logMessage(const char * message,int level) const135 virtual void logMessage(const char *message, int level) const {
136 SWBuf msg = message;
137 if (msg.size() > 512) msg.setSize(512);
138 __android_log_write(levelMapping[level], "libsword.so", msg.c_str());
139 }
140 };
141
142
init(JNIEnv * env)143 static void init(JNIEnv *env) {
144 if (!mgr) {
145 SWLog::setSystemLog(new AndroidLogger());
146 SWLog::getSystemLog()->setLogLevel(SWLog::LOG_DEBUG);
147 SWLog::getSystemLog()->logDebug("libsword: init() begin");
148 SWBuf baseDir = SWORD_PATH;
149 SWBuf confPath = baseDir + "/mods.d/globals.conf";
150 // be sure we have at least some config file already out there
151 if (!FileMgr::existsFile(confPath.c_str())) {
152 SWLog::getSystemLog()->logDebug("libsword: init() sword config not found, attempting to create parent of: %s", confPath.c_str());
153 FileMgr::createParent(confPath.c_str());
154 remove(confPath.c_str());
155
156 SWLog::getSystemLog()->logDebug("libsword: init() saving basic: %s", confPath.c_str());
157 SWConfig config(confPath.c_str());
158 config["Globals"]["HiAndroid"] = "weeee";
159 config.save();
160 }
161 if (!FileMgr::existsFile(confPath.c_str())) {
162 baseDir = STORAGE_BASE;
163 confPath = baseDir + "/mods.d/globals.conf";
164 SWLog::getSystemLog()->logDebug("libsword: init() sword config STILL not found, attempting to create parent of: %s", confPath.c_str());
165 FileMgr::createParent(confPath.c_str());
166 remove(confPath.c_str());
167
168 SWLog::getSystemLog()->logDebug("libsword: init() saving basic: %s", confPath.c_str());
169 SWConfig config(confPath.c_str());
170 config["Globals"]["HiAndroid"] = "weeee";
171 config.save();
172 }
173 confPath = STORAGE_BASE + "/extraConfig.conf";
174 bool exists = FileMgr::existsFile(confPath.c_str());
175 SWLog::getSystemLog()->logDebug("libsword: extraConfig %s at path: %s", exists?"Exists":"Absent", confPath.c_str());
176
177 SWLog::getSystemLog()->logDebug("libsword: init() creating WebMgr using path: %s", baseDir.c_str());
178 mgr = new WebMgr(baseDir, exists?confPath.c_str():0);
179
180 SWLog::getSystemLog()->logDebug("libsword: init() augmenting modules from: %s", AND_BIBLE_MODULES_PATH);
181 // for And Bible modules
182 mgr->augmentModules(AND_BIBLE_MODULES_PATH, true);
183 }
184 }
185
initInstall(JNIEnv * env,jobject progressReporter=0)186 static void initInstall(JNIEnv *env, jobject progressReporter = 0) {
187
188 if (!installStatusReporter) {
189 installStatusReporter = new InstallStatusReporter();
190 }
191 installStatusReporter->init(env, progressReporter);
192 if (!installMgr) {
193 SWLog::getSystemLog()->logDebug("initInstall: installMgr is null");
194 SWBuf baseDir = SWORD_PATH;
195 baseDir += "/InstallMgr";
196 SWBuf confPath = baseDir + "/InstallMgr.conf";
197 // be sure we have at least some config file already out there
198 SWLog::getSystemLog()->logDebug("initInstall: confPath: %s", confPath.c_str());
199 if (!FileMgr::existsFile(confPath.c_str())) {
200 SWLog::getSystemLog()->logDebug("initInstall: file doesn't exist: %s", confPath.c_str());
201 FileMgr::createParent(confPath.c_str());
202 SWConfig config(confPath.c_str());
203 config["General"]["PassiveFTP"] = "true";
204 config.save();
205 }
206 if (!FileMgr::existsFile(confPath.c_str())) {
207 baseDir = STORAGE_BASE;
208 confPath = baseDir + "/InstallMgr.conf";
209 SWLog::getSystemLog()->logDebug("initInstall: file STILL doesn't exist, attempting to create parent of: %s", confPath.c_str());
210 FileMgr::createParent(confPath.c_str());
211 SWConfig config(confPath.c_str());
212 config["General"]["PassiveFTP"] = "true";
213 config.save();
214 }
215 installMgr = new InstallMgr(baseDir, installStatusReporter);
216 if (disclaimerConfirmed) installMgr->setUserDisclaimerConfirmed(true);
217 SWLog::getSystemLog()->logDebug("initInstall: instantiated InstallMgr with baseDir: %s", baseDir.c_str());
218 }
219 }
220
221 #ifdef BIBLESYNC
bibleSyncCallback(char cmd,string bible,string ref,string alt,string group,string domain,string info,string dump)222 void bibleSyncCallback(char cmd, string bible, string ref, string alt, string group, string domain, string info, string dump) {
223 SWLog::getSystemLog()->logDebug("bibleSync callback msg: %c; bible: %s; ref: %s; alt: %s; group: %s; domain: %s; info: %s; dump: %s", cmd, bible.c_str(), ref.c_str(), alt.c_str(), group.c_str(), domain.c_str(), info.c_str(), dump.c_str());
224 if (::bibleSyncListener) {
225 SWLog::getSystemLog()->logDebug("bibleSync listener is true");
226 jclass cls = bibleSyncListenerEnv->GetObjectClass(::bibleSyncListener);
227 jmethodID mid = bibleSyncListenerEnv->GetMethodID(cls, "messageReceived", "(Ljava/lang/String;)V");
228 SWLog::getSystemLog()->logDebug("bibleSync listener mid: %ld", mid);
229 if (mid) {
230 SWLog::getSystemLog()->logDebug("bibleSync listener mid is available");
231 switch(cmd) {
232 // error
233 case 'E':
234 // mismatch
235 case 'M':
236 // new speaker
237 case 'S':
238 // dead speaker
239 case 'D':
240 // announce
241 case 'A':
242 break;
243 // navigation
244 case 'N':
245 SWLog::getSystemLog()->logDebug("bibleSync Nav Received: %s", ref.c_str());
246 jstring msg = bibleSyncListenerEnv->NewStringUTF(ref.c_str());
247 bibleSyncListenerEnv->CallVoidMethod(::bibleSyncListener, mid, msg);
248 bibleSyncListenerEnv->DeleteLocalRef(msg);
249 break;
250 }
251 }
252 SWLog::getSystemLog()->logDebug("bibleSync listener deleting local ref to cls");
253 bibleSyncListenerEnv->DeleteLocalRef(cls);
254 }
255 }
256 #endif
257
258
initBibleSync()259 static void initBibleSync() {
260 #ifdef BIBLESYNC
261 if (!bibleSync) {
262 SWLog::getSystemLog()->logDebug("bibleSync initializing c-tor");
263 bibleSync = new BibleSync("SWORD", (const char *)SWVersion().currentVersion, "SwordUser");
264 SWLog::getSystemLog()->logDebug("bibleSync initializing setMode");
265 bibleSync->setMode(BSP_MODE_PERSONAL, bibleSyncCallback, "passphrase");
266 }
267 #endif
268 }
269
270 }
271
272
Java_org_crosswire_android_sword_SWMgr_version(JNIEnv * env,jobject me)273 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWMgr_version
274 (JNIEnv *env, jobject me) {
275
276 init(env);
277
278 SWVersion v;
279 return env->NewStringUTF(v.currentVersion);
280 }
281
282
283 /*
284 * Class: org_crosswire_android_sword_SWMgr
285 * Method: reInit
286 * Signature: ()V
287 */
Java_org_crosswire_android_sword_SWMgr_reInit(JNIEnv * env,jobject me)288 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_reInit
289 (JNIEnv *env, jobject me) {
290
291 jclass swmgrClass = env->GetObjectClass(me);
292 jmethodID getStorageBasePath = env->GetMethodID(swmgrClass, "getStorageBasePath", "()Ljava/lang/String;");
293 jstring basePathJS = (jstring)env->CallObjectMethod(me, getStorageBasePath, NULL);
294
295 const char *basePath = (basePathJS?env->GetStringUTFChars(basePathJS, NULL):0);
296 STORAGE_BASE = basePath;
297 SWLog::getSystemLog()->logDebug("setting STORAGE_BASE to: %s", STORAGE_BASE.c_str());
298
299 delete mgr;
300 mgr = 0;
301 }
302
303
Java_org_crosswire_android_sword_SWMgr_getPrefixPath(JNIEnv * env,jobject me)304 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWMgr_getPrefixPath
305 (JNIEnv *env, jobject me) {
306
307 init(env);
308
309 return env->NewStringUTF(mgr->prefixPath);
310 }
311
Java_org_crosswire_android_sword_SWMgr_getConfigPath(JNIEnv * env,jobject me)312 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWMgr_getConfigPath
313 (JNIEnv *env, jobject me) {
314
315 init(env);
316
317 return env->NewStringUTF(mgr->configPath);
318 }
319
320
Java_org_crosswire_android_sword_SWMgr_getModInfoList(JNIEnv * env,jobject)321 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWMgr_getModInfoList
322 (JNIEnv *env, jobject) {
323
324 init(env);
325
326 int size = 0;
327 for (sword::ModMap::iterator it = mgr->Modules.begin(); it != mgr->Modules.end(); ++it) {
328 if ((!(it->second->getConfigEntry("CipherKey"))) || (*(it->second->getConfigEntry("CipherKey"))))
329 size++;
330 }
331
332 SWLog::getSystemLog()->logDebug("getModInfoList returning %d length array\n", size);
333
334 jclass clazzModInfo = env->FindClass("org/crosswire/android/sword/SWMgr$ModInfo");
335 jfieldID nameID = env->GetFieldID(clazzModInfo, "name", "Ljava/lang/String;");
336 jfieldID descID = env->GetFieldID(clazzModInfo, "description", "Ljava/lang/String;");
337 jfieldID catID = env->GetFieldID(clazzModInfo, "category", "Ljava/lang/String;");
338 jfieldID langID = env->GetFieldID(clazzModInfo, "language", "Ljava/lang/String;");
339 jfieldID versionID = env->GetFieldID(clazzModInfo, "version", "Ljava/lang/String;");
340 jfieldID deltaID = env->GetFieldID(clazzModInfo, "delta", "Ljava/lang/String;");
341
342 jobjectArray ret = (jobjectArray) env->NewObjectArray(size, clazzModInfo, NULL);
343
344 int i = 0;
345 for (sword::ModMap::iterator it = mgr->Modules.begin(); it != mgr->Modules.end(); ++it) {
346 SWModule *module = it->second;
347
348 if ((!(module->getConfigEntry("CipherKey"))) || (*(module->getConfigEntry("CipherKey")))) {
349 SWBuf type = module->getType();
350 SWBuf cat = module->getConfigEntry("Category");
351 SWBuf version = module->getConfigEntry("Version");
352 if (cat.length() > 0) type = cat;
353
354 jobject modInfo = env->AllocObject(clazzModInfo);
355
356 jstring val;
357 val = env->NewStringUTF(assureValidUTF8(module->getName())); env->SetObjectField(modInfo, nameID , val); env->DeleteLocalRef(val);
358 val = env->NewStringUTF(assureValidUTF8(module->getDescription())); env->SetObjectField(modInfo, descID , val); env->DeleteLocalRef(val);
359 val = env->NewStringUTF(assureValidUTF8(type.c_str())); env->SetObjectField(modInfo, catID , val); env->DeleteLocalRef(val);
360 val = env->NewStringUTF(assureValidUTF8(module->getLanguage())); env->SetObjectField(modInfo, langID , val); env->DeleteLocalRef(val);
361 val = env->NewStringUTF(assureValidUTF8(version.c_str())); env->SetObjectField(modInfo, versionID, val); env->DeleteLocalRef(val);
362 val = env->NewStringUTF(assureValidUTF8("")); env->SetObjectField(modInfo, deltaID , val); env->DeleteLocalRef(val);
363
364 env->SetObjectArrayElement(ret, i++, modInfo);
365
366 env->DeleteLocalRef(modInfo);
367
368 }
369 }
370 return ret;
371 }
372
373 /*
374 * Class: org_crosswire_android_sword_SWMgr
375 * Method: getModuleByName
376 * Signature: (Ljava/lang/String;)Lorg/crosswire/android/sword/SWModule;
377 */
Java_org_crosswire_android_sword_SWMgr_getModuleByName(JNIEnv * env,jobject me,jstring modNameJS)378 JNIEXPORT jobject JNICALL Java_org_crosswire_android_sword_SWMgr_getModuleByName
379 (JNIEnv *env, jobject me, jstring modNameJS) {
380
381 init(env);
382
383 jobject retVal = 0;
384
385 const char *modName = env->GetStringUTFChars(modNameJS, NULL);
386 sword::SWModule *module = mgr->getModule(modName);
387 env->ReleaseStringUTFChars(modNameJS, modName);
388
389 if (module) {
390 SWBuf type = module->getType();
391 SWBuf cat = module->getConfigEntry("Category");
392 if (cat.length() > 0) type = cat;
393 jfieldID fieldID;
394 jclass clazzSWModule = env->FindClass("org/crosswire/android/sword/SWModule");
395 retVal = env->AllocObject(clazzSWModule);
396 fieldID = env->GetFieldID(clazzSWModule, "name", "Ljava/lang/String;"); env->SetObjectField(retVal, fieldID, env->NewStringUTF(assureValidUTF8(module->getName())));
397 fieldID = env->GetFieldID(clazzSWModule, "description", "Ljava/lang/String;"); env->SetObjectField(retVal, fieldID, env->NewStringUTF(assureValidUTF8(module->getDescription())));
398 fieldID = env->GetFieldID(clazzSWModule, "category", "Ljava/lang/String;"); env->SetObjectField(retVal, fieldID, env->NewStringUTF(assureValidUTF8(type.c_str())));
399 }
400 return retVal;
401 }
402
403
404 /*
405 * Class: org_crosswire_android_sword_SWMgr
406 * Method: setGlobalOption
407 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
408 */
Java_org_crosswire_android_sword_SWMgr_setGlobalOption(JNIEnv * env,jobject me,jstring optionJS,jstring valueJS)409 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_setGlobalOption
410 (JNIEnv *env, jobject me, jstring optionJS, jstring valueJS) {
411
412 init(env);
413
414 const char *option = env->GetStringUTFChars(optionJS, NULL);
415 const char *value = env->GetStringUTFChars(valueJS, NULL);
416
417 mgr->setGlobalOption(option, value);
418
419 env->ReleaseStringUTFChars(valueJS, value);
420 env->ReleaseStringUTFChars(optionJS, option);
421 }
422
423
424 /*
425 * Class: org_crosswire_android_sword_SWMgr
426 * Method: getGlobalOption
427 * Signature: (Ljava/lang/String;)Ljava/lang/String;
428 */
Java_org_crosswire_android_sword_SWMgr_getGlobalOption(JNIEnv * env,jobject me,jstring optionJS)429 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWMgr_getGlobalOption
430 (JNIEnv *env, jobject me, jstring optionJS) {
431
432 init(env);
433
434 const char *option = env->GetStringUTFChars(optionJS, NULL);
435
436 SWBuf value = mgr->getGlobalOption(option);
437
438 env->ReleaseStringUTFChars(optionJS, option);
439
440 return env->NewStringUTF(assureValidUTF8(value));
441 }
442
443
444 /*
445 * Class: org_crosswire_android_sword_SWMgr
446 * Method: getGlobalOptionTip
447 * Signature: (Ljava/lang/String;)Ljava/lang/String;
448 */
Java_org_crosswire_android_sword_SWMgr_getGlobalOptionTip(JNIEnv * env,jobject me,jstring optionJS)449 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWMgr_getGlobalOptionTip
450 (JNIEnv *env, jobject me, jstring optionJS) {
451
452 init(env);
453
454 const char *option = env->GetStringUTFChars(optionJS, NULL);
455
456 SWBuf value = mgr->getGlobalOptionTip(option);
457
458 env->ReleaseStringUTFChars(optionJS, option);
459
460 return env->NewStringUTF(assureValidUTF8(value));
461 }
462
463
464 /*
465 * Class: org_crosswire_android_sword_SWMgr
466 * Method: filterText
467 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
468 */
Java_org_crosswire_android_sword_SWMgr_filterText(JNIEnv * env,jobject me,jstring filterNameJS,jstring textJS)469 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWMgr_filterText
470 (JNIEnv *env, jobject me, jstring filterNameJS, jstring textJS) {
471
472 init(env);
473
474 const char *filterName = env->GetStringUTFChars(filterNameJS, NULL);
475 const char *text = env->GetStringUTFChars(textJS, NULL);
476
477 SWBuf buf = text;
478 // hmmm, in the future, provide a param to specify filter value maybe?
479 mgr->setGlobalOption("Greek Accents", "Off");
480 char errStatus = mgr->filterText(filterName, buf);
481
482 env->ReleaseStringUTFChars(textJS, text);
483 env->ReleaseStringUTFChars(filterNameJS, filterName);
484
485 return env->NewStringUTF(assureValidUTF8(buf));
486 }
487
488
489 /*
490 * Class: org_crosswire_android_sword_SWMgr
491 * Method: getGlobalOptions
492 * Signature: ()[Ljava/lang/String;
493 */
Java_org_crosswire_android_sword_SWMgr_getGlobalOptions(JNIEnv * env,jobject me)494 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWMgr_getGlobalOptions
495 (JNIEnv *env, jobject me) {
496
497 init(env);
498
499 sword::StringList options = mgr->getGlobalOptions();
500 int count = 0;
501 for (sword::StringList::iterator it = options.begin(); it != options.end(); ++it) {
502 count++;
503 }
504
505 jclass clazzString = env->FindClass("java/lang/String");
506 jobjectArray ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
507
508 count = 0;
509 for (sword::StringList::iterator it = options.begin(); it != options.end(); ++it) {
510 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8(*it)));
511 }
512
513 return ret;
514 }
515
516
517 /*
518 * Class: org_crosswire_android_sword_SWMgr
519 * Method: getExtraConfigSections
520 * Signature: ()[Ljava/lang/String;
521 */
Java_org_crosswire_android_sword_SWMgr_getExtraConfigSections(JNIEnv * env,jobject me)522 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWMgr_getExtraConfigSections
523 (JNIEnv *env, jobject me) {
524
525 init(env);
526
527 SWBuf baseDir = STORAGE_BASE;
528 SWBuf confPath = baseDir + "/extraConfig.conf";
529 int count = 0;
530 bool exists = FileMgr::existsFile(confPath.c_str());
531 jclass clazzString = env->FindClass("java/lang/String");
532 jobjectArray ret;
533 SWLog::getSystemLog()->logDebug("libsword: extraConfig %s at path: %s", exists?"Exists":"Absent", confPath.c_str());
534 if (exists) {
535 SWConfig config(confPath.c_str());
536 SectionMap::const_iterator sit;
537 for (sit = config.getSections().begin(); sit != config.getSections().end(); ++sit) {
538 count++;
539 }
540 SWLog::getSystemLog()->logDebug("libsword: %d sections found in extraConfig", count);
541 ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
542 count = 0;
543 for (sit = config.getSections().begin(); sit != config.getSections().end(); ++sit) {
544 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8(sit->first.c_str())));
545 }
546 }
547 else {
548 ret = (jobjectArray) env->NewObjectArray(0, clazzString, NULL);
549 }
550
551 return ret;
552 }
553
554
555 /*
556 * Class: org_crosswire_android_sword_SWMgr
557 * Method: getExtraConfigKeys
558 * Signature: (Ljava/lang/String;)[Ljava/lang/String;
559 */
Java_org_crosswire_android_sword_SWMgr_getExtraConfigKeys(JNIEnv * env,jobject me,jstring section)560 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWMgr_getExtraConfigKeys
561 (JNIEnv *env, jobject me, jstring section) {
562
563 init(env);
564
565 const char *s = env->GetStringUTFChars(section, NULL);
566
567 SWBuf mySection = s;
568
569 env->ReleaseStringUTFChars(section, s);
570
571 SWBuf baseDir = STORAGE_BASE;
572 SWBuf confPath = baseDir + "/extraConfig.conf";
573 int count = 0;
574 bool exists = FileMgr::existsFile(confPath.c_str());
575 jclass clazzString = env->FindClass("java/lang/String");
576 jobjectArray ret;
577 if (exists) {
578 SWConfig config(confPath.c_str());
579 SectionMap::const_iterator sit = config.getSections().find(mySection.c_str());
580 if (sit != config.getSections().end()) {
581 ConfigEntMap::const_iterator it;
582 for (it = sit->second.begin(); it != sit->second.end(); ++it) {
583 count++;
584 }
585 ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
586 count = 0;
587 for (it = sit->second.begin(); it != sit->second.end(); ++it) {
588 env->SetObjectArrayElement(ret, count++,
589 env->NewStringUTF(assureValidUTF8(it->first.c_str())));
590 }
591 }
592 else {
593 ret = (jobjectArray) env->NewObjectArray(0, clazzString, NULL);
594 }
595 }
596 else {
597 ret = (jobjectArray) env->NewObjectArray(0, clazzString, NULL);
598 }
599
600 return ret;
601 }
602
603
604 /*
605 * Class: org_crosswire_android_sword_SWMgr
606 * Method: getExtraConfigValue
607 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
608 */
Java_org_crosswire_android_sword_SWMgr_getExtraConfigValue(JNIEnv * env,jobject me,jstring section,jstring key)609 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWMgr_getExtraConfigValue
610 (JNIEnv *env, jobject me, jstring section, jstring key) {
611
612 init(env);
613
614 const char *s = env->GetStringUTFChars(section, NULL);
615
616 SWBuf mySection = s;
617
618 env->ReleaseStringUTFChars(section, s);
619
620 const char *k = env->GetStringUTFChars(key, NULL);
621
622 SWBuf myKey = k;
623
624 env->ReleaseStringUTFChars(key, k);
625
626 jstring ret = 0;
627
628 SWBuf baseDir = STORAGE_BASE;
629 SWBuf confPath = baseDir + "/extraConfig.conf";
630 bool exists = FileMgr::existsFile(confPath.c_str());
631 if (exists) {
632 SWConfig config(confPath.c_str());
633 SectionMap::const_iterator sit = config.getSections().find(mySection.c_str());
634 if (sit != config.getSections().end()) {
635 ConfigEntMap::const_iterator it = sit->second.find(myKey.c_str());
636 if (it != sit->second.end()) {
637 ret = env->NewStringUTF(assureValidUTF8(it->second.c_str()));
638 }
639 }
640 }
641
642 return ret;
643 }
644
645
646 /*
647 * Class: org_crosswire_android_sword_SWMgr
648 * Method: setExtraConfigValue
649 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
650 */
Java_org_crosswire_android_sword_SWMgr_setExtraConfigValue(JNIEnv * env,jobject me,jstring section,jstring key,jstring value)651 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_setExtraConfigValue
652 (JNIEnv *env, jobject me, jstring section, jstring key, jstring value) {
653
654 init(env);
655
656 const char *s = env->GetStringUTFChars(section, NULL);
657
658 SWBuf mySection = s;
659
660 env->ReleaseStringUTFChars(section, s);
661
662 const char *k = env->GetStringUTFChars(key, NULL);
663
664 SWBuf myKey = k;
665
666 env->ReleaseStringUTFChars(key, k);
667
668 const char *v = env->GetStringUTFChars(value, NULL);
669
670 SWBuf myValue = v;
671
672 env->ReleaseStringUTFChars(value, v);
673
674 SWBuf baseDir = STORAGE_BASE;
675 SWBuf confPath = baseDir + "/extraConfig.conf";
676 SWConfig config(confPath.c_str());
677 config[mySection][myKey] = myValue;
678 config.save();
679
680 Java_org_crosswire_android_sword_SWMgr_reInit(env, me);
681
682 }
683
684
685 /*
686 * Class: org_crosswire_android_sword_SWMgr
687 * Method: addExtraConfig
688 * Signature: (Ljava/lang/String;)[Ljava/lang/String;
689 */
Java_org_crosswire_android_sword_SWMgr_addExtraConfig(JNIEnv * env,jobject me,jstring blob)690 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWMgr_addExtraConfig
691 (JNIEnv *env, jobject me, jstring blob) {
692
693 init(env);
694
695 const char *b = env->GetStringUTFChars(blob, NULL);
696
697 SWBuf myBlob = b;
698
699 env->ReleaseStringUTFChars(blob, b);
700
701 jobjectArray ret;
702
703 int count = 0;
704 jclass clazzString = env->FindClass("java/lang/String");
705
706 SWBuf baseDir = STORAGE_BASE;
707 SWBuf tmpConfPath = baseDir + "/tmpConfig.conf";
708 FileMgr::removeFile(tmpConfPath.c_str());
709 FileDesc *fd = FileMgr::getSystemFileMgr()->open(tmpConfPath.c_str(), FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE);
710 fd->getFd();
711 fd->write(myBlob.c_str(), myBlob.size());
712 FileMgr::getSystemFileMgr()->close(fd);
713
714 SWConfig newConfig(tmpConfPath.c_str());
715 FileMgr::removeFile(tmpConfPath.c_str());
716 SectionMap::const_iterator sit;
717 for (sit = newConfig.getSections().begin(); sit != newConfig.getSections().end(); ++sit) {
718 count++;
719 }
720 ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
721 count = 0;
722 for (sit = newConfig.getSections().begin(); sit != newConfig.getSections().end(); ++sit) {
723 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8(sit->first.c_str())));
724 }
725
726 SWBuf confPath = baseDir + "/extraConfig.conf";
727 SWConfig config(confPath.c_str());
728 config.augment(newConfig);
729 config.save();
730
731 Java_org_crosswire_android_sword_SWMgr_reInit(env, me);
732
733 return ret;
734 }
735
736
737 /*
738 * Class: org_crosswire_android_sword_SWMgr
739 * Method: getGlobalOptionValues
740 * Signature: (Ljava/lang/String;)[Ljava/lang/String;
741 */
Java_org_crosswire_android_sword_SWMgr_getGlobalOptionValues(JNIEnv * env,jobject me,jstring optionJS)742 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWMgr_getGlobalOptionValues
743 (JNIEnv *env, jobject me, jstring optionJS) {
744
745 init(env);
746
747 const char *option = env->GetStringUTFChars(optionJS, NULL);
748
749 sword::StringList options = mgr->getGlobalOptionValues(option);
750
751 env->ReleaseStringUTFChars(optionJS, option);
752
753 int count = 0;
754 for (sword::StringList::iterator it = options.begin(); it != options.end(); ++it) {
755 count++;
756 }
757 jclass clazzString = env->FindClass("java/lang/String");
758 jobjectArray ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
759
760 count = 0;
761 for (sword::StringList::iterator it = options.begin(); it != options.end(); ++it) {
762 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8(*it)));
763 }
764
765 return ret;
766 }
767
768
769 /*
770 * Class: org_crosswire_android_sword_SWMgr
771 * Method: setCipherKey
772 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
773 */
Java_org_crosswire_android_sword_SWMgr_setCipherKey(JNIEnv * env,jobject me,jstring modNameJS,jstring keyJS)774 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_setCipherKey
775 (JNIEnv *env, jobject me , jstring modNameJS, jstring keyJS) {
776
777 init(env);
778
779 const char *modName = env->GetStringUTFChars(modNameJS, NULL);
780 const char *key = env->GetStringUTFChars(keyJS, NULL);
781
782 mgr->setCipherKey(modName, key);
783
784 env->ReleaseStringUTFChars(keyJS, key);
785 env->ReleaseStringUTFChars(modNameJS, modName);
786 }
787
788
789 /*
790 * Class: org_crosswire_android_sword_SWMgr
791 * Method: setJavascript
792 * Signature: (Z)V
793 */
Java_org_crosswire_android_sword_SWMgr_setJavascript(JNIEnv * env,jobject me,jboolean val)794 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_setJavascript
795 (JNIEnv *env, jobject me, jboolean val) {
796
797 init(env);
798
799 mgr->setJavascript(val == JNI_TRUE);
800 }
801
802
803 /*
804 * Class: org_crosswire_android_sword_SWMgr
805 * Method: getAvailableLocales
806 * Signature: ()[Ljava/lang/String;
807 */
Java_org_crosswire_android_sword_SWMgr_getAvailableLocales(JNIEnv * env,jobject me)808 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWMgr_getAvailableLocales
809 (JNIEnv *env, jobject me) {
810
811 init(env);
812
813 sword::StringList localeNames = LocaleMgr::getSystemLocaleMgr()->getAvailableLocales();
814 int count = 0;
815 for (sword::StringList::iterator it = localeNames.begin(); it != localeNames.end(); ++it) {
816 count++;
817 }
818
819 jclass clazzString = env->FindClass("java/lang/String");
820 jobjectArray ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
821
822 count = 0;
823 for (sword::StringList::iterator it = localeNames.begin(); it != localeNames.end(); ++it) {
824 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8(*it)));
825 }
826 return ret;
827 }
828
829
830 /*
831 * Class: org_crosswire_android_sword_SWMgr
832 * Method: setDefaultLocale
833 * Signature: (Ljava/lang/String;)V
834 */
Java_org_crosswire_android_sword_SWMgr_setDefaultLocale(JNIEnv * env,jobject me,jstring localeNameJS)835 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_setDefaultLocale
836 (JNIEnv *env, jobject me, jstring localeNameJS) {
837
838 init(env);
839
840 const char *localeName = env->GetStringUTFChars(localeNameJS, NULL);
841
842 LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName(localeName);
843
844 env->ReleaseStringUTFChars(localeNameJS, localeName);
845 }
846
847
848
849 // SWModule methods ----------------------------------------------------------------------------------
850
851
getModule(JNIEnv * env,jobject me)852 SWModule *getModule
853 (JNIEnv *env, jobject me) {
854
855 init(env);
856
857 SWModule *module = 0;
858 jclass clazzSWModule = env->FindClass("org/crosswire/android/sword/SWModule");
859 jfieldID fieldID = env->GetFieldID(clazzSWModule, "name", "Ljava/lang/String;");
860 jfieldID sourceFieldID = env->GetFieldID(clazzSWModule, "remoteSourceName", "Ljava/lang/String;");
861 jstring modNameJS = (jstring)env->GetObjectField(me, fieldID);
862 jstring sourceNameJS = (jstring)env->GetObjectField(me, sourceFieldID);
863 const char *modName = (modNameJS?env->GetStringUTFChars(modNameJS, NULL):0);
864 const char *sourceName = (sourceNameJS?env->GetStringUTFChars(sourceNameJS, NULL):0);
865 if (sourceName && *sourceName) {
866 initInstall(env);
867 InstallSourceMap::iterator source = installMgr->sources.find(sourceName);
868 if (source == installMgr->sources.end()) {
869 SWMgr *mgr = source->second->getMgr();
870 module = mgr->getModule(modName);
871 }
872 }
873 else module = mgr->getModule(modName);
874 if (modName) env->ReleaseStringUTFChars(modNameJS, modName);
875 if (sourceName) env->ReleaseStringUTFChars(sourceNameJS, sourceName);
876 return module;
877 }
878
879 /*
880 * Class: org_crosswire_android_sword_SWModule
881 * Method: setKeyText
882 * Signature: (Ljava/lang/String;)V
883 */
Java_org_crosswire_android_sword_SWModule_setKeyText(JNIEnv * env,jobject me,jstring keyTextJS)884 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWModule_setKeyText
885 (JNIEnv *env, jobject me, jstring keyTextJS) {
886
887 init(env);
888
889 SWModule *module = getModule(env, me);
890
891 if (module) {
892 const char *keyText = env->GetStringUTFChars(keyTextJS, NULL);
893 SWLog::getSystemLog()->logDebug("setKeyText(%s, %s)", module->getName(), keyText);
894 sword::SWKey *key = module->getKey();
895 sword::VerseKey *vkey = SWDYNAMIC_CAST(VerseKey, key);
896 if (vkey && (*keyText=='+' ||*keyText=='-')) {
897 if (!stricmp(keyText+1, "book")) {
898 int newBook = vkey->getBook() + ((*keyText=='+')?1:-1);
899 SWLog::getSystemLog()->logDebug("setting book to %d", newBook);
900 vkey->setBook(newBook);
901 env->ReleaseStringUTFChars(keyTextJS, keyText);
902 return;
903 }
904 else if (!stricmp(keyText+1, "chapter")) {
905 vkey->setChapter(vkey->getChapter() + ((*keyText=='+')?1:-1));
906 env->ReleaseStringUTFChars(keyTextJS, keyText);
907 return;
908 }
909 }
910
911 module->setKey(keyText);
912 env->ReleaseStringUTFChars(keyTextJS, keyText);
913 }
914 }
915
916
917 /*
918 * Class: org_crosswire_android_sword_SWModule
919 * Method: getKeyText
920 * Signature: ()Ljava/lang/String;
921 */
Java_org_crosswire_android_sword_SWModule_getKeyText(JNIEnv * env,jobject me)922 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWModule_getKeyText
923 (JNIEnv *env, jobject me) {
924
925 init(env);
926
927 SWModule *module = getModule(env, me);
928
929 jstring retVal = 0;
930 if (module) {
931 retVal = env->NewStringUTF(assureValidUTF8(module->getKeyText()));
932 }
933 return retVal;
934 }
935
936
937 /*
938 * Class: org_crosswire_android_sword_SWModule
939 * Method: getRenderText
940 * Signature: ()Ljava/lang/String;
941 */
Java_org_crosswire_android_sword_SWModule_getRenderText(JNIEnv * env,jobject me)942 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWModule_getRenderText
943 (JNIEnv *env, jobject me) {
944
945 init(env);
946
947 SWModule *module = getModule(env, me);
948
949 jstring retVal = 0;
950 if (module) {
951 retVal = env->NewStringUTF(assureValidUTF8(module->renderText()));
952 }
953 return retVal;
954 }
955
956
957 /*
958 * Class: org_crosswire_android_sword_SWModule
959 * Method: getRenderHeader
960 * Signature: ()Ljava/lang/String;
961 */
Java_org_crosswire_android_sword_SWModule_getRenderHeader(JNIEnv * env,jobject me)962 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWModule_getRenderHeader
963 (JNIEnv *env, jobject me) {
964
965 init(env);
966
967 SWModule *module = getModule(env, me);
968
969 jstring retVal = 0;
970 if (module) {
971 retVal = env->NewStringUTF(assureValidUTF8(((const char *)(module->getRenderHeader() ? module->getRenderHeader():""))));
972 }
973 return retVal;
974 }
975
976
977 /*
978 * Class: org_crosswire_android_sword_SWModule
979 * Method: terminateSearch
980 * Signature: ()V
981 */
Java_org_crosswire_android_sword_SWModule_terminateSearch(JNIEnv * env,jobject me)982 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWModule_terminateSearch
983 (JNIEnv *env, jobject me) {
984
985 init(env);
986
987 SWModule *module = getModule(env, me);
988
989 if (module) {
990 module->terminateSearch = true;
991 }
992 }
993
994
995 /*
996 * Class: org_crosswire_android_sword_SWModule
997 * Method: error
998 * Signature: ()C
999 */
Java_org_crosswire_android_sword_SWModule_error(JNIEnv * env,jobject me)1000 JNIEXPORT jchar JNICALL Java_org_crosswire_android_sword_SWModule_error
1001 (JNIEnv *env, jobject me) {
1002
1003 init(env);
1004
1005 SWModule *module = getModule(env, me);
1006
1007 int error = (module) ? module->popError() : -99;
1008 return error;
1009 }
1010
1011
1012 /*
1013 * Class: org_crosswire_android_sword_SWModule
1014 * Method: getEntrySize
1015 * Signature: ()J
1016 */
Java_org_crosswire_android_sword_SWModule_getEntrySize(JNIEnv * env,jobject me)1017 JNIEXPORT jlong JNICALL Java_org_crosswire_android_sword_SWModule_getEntrySize
1018 (JNIEnv *env, jobject me) {
1019
1020 init(env);
1021
1022 SWModule *module = getModule(env, me);
1023
1024 return (module) ? module->getEntrySize() : 0;
1025 }
1026
1027
1028 /*
1029 * Class: org_crosswire_android_sword_SWModule
1030 * Method: getEntryAttribute
1031 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)[Ljava/lang/String;
1032 */
Java_org_crosswire_android_sword_SWModule_getEntryAttribute(JNIEnv * env,jobject me,jstring level1JS,jstring level2JS,jstring level3JS,jboolean filteredJS)1033 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWModule_getEntryAttribute
1034 (JNIEnv *env, jobject me, jstring level1JS, jstring level2JS, jstring level3JS, jboolean filteredJS) {
1035
1036 init(env);
1037
1038 const char *level1 = env->GetStringUTFChars(level1JS, NULL);
1039 const char *level2 = env->GetStringUTFChars(level2JS, NULL);
1040 const char *level3 = env->GetStringUTFChars(level3JS, NULL);
1041 bool filtered = (filteredJS == JNI_TRUE);
1042
1043 jclass clazzString = env->FindClass("java/lang/String");
1044 jobjectArray ret = 0;
1045
1046 SWModule *module = getModule(env, me);
1047
1048 if (module) {
1049
1050 module->renderText(); // force parse
1051 vector<SWBuf> results;
1052
1053 sword::AttributeTypeList &entryAttribs = module->getEntryAttributes();
1054 sword::AttributeTypeList::iterator i1Start, i1End;
1055 sword::AttributeList::iterator i2Start, i2End;
1056 sword::AttributeValue::iterator i3Start, i3End;
1057
1058 if ((level1) && (*level1) && *level1 != '-') {
1059 i1Start = entryAttribs.find(level1);
1060 i1End = i1Start;
1061 if (i1End != entryAttribs.end())
1062 ++i1End;
1063 }
1064 else {
1065 i1Start = entryAttribs.begin();
1066 i1End = entryAttribs.end();
1067 }
1068 for (;i1Start != i1End; ++i1Start) {
1069 if (level1 && *level1 && *level1 == '-') {
1070 results.push_back(i1Start->first);
1071 }
1072 else {
1073 if (level2 && *level2 && *level2 != '-') {
1074 i2Start = i1Start->second.find(level2);
1075 i2End = i2Start;
1076 if (i2End != i1Start->second.end())
1077 ++i2End;
1078 }
1079 else {
1080 i2Start = i1Start->second.begin();
1081 i2End = i1Start->second.end();
1082 }
1083 for (;i2Start != i2End; ++i2Start) {
1084 if (level2 && *level2 && *level2 == '-') {
1085 results.push_back(i2Start->first);
1086 }
1087 else {
1088 // allow '-' to get all keys; allow '*' to get all key=value
1089 if (level3 && *level3 && *level3 != '-' && *level3 != '*') {
1090 i3Start = i2Start->second.find(level3);
1091 i3End = i3Start;
1092 if (i3End != i2Start->second.end())
1093 ++i3End;
1094 }
1095 else {
1096 i3Start = i2Start->second.begin();
1097 i3End = i2Start->second.end();
1098 }
1099 for (;i3Start != i3End; ++i3Start) {
1100 if (level3 && *level3 && *level3 == '-') {
1101 results.push_back(i3Start->first);
1102 }
1103 else if (level3 && *level3 && *level3 == '*') {
1104 results.push_back(i3Start->first + "=" + i3Start->second);
1105 }
1106 else {
1107 results.push_back(i3Start->second);
1108 }
1109 }
1110 if (i3Start != i3End)
1111 break;
1112 }
1113 }
1114 if (i2Start != i2End)
1115 break;
1116 }
1117 }
1118
1119 ret = (jobjectArray) env->NewObjectArray(results.size(), clazzString, NULL);
1120
1121 SWLog::getSystemLog()->logDebug("getEntryAttributes: size returned: %d", results.size());
1122
1123 for (int i = 0; i < results.size(); i++) {
1124 if (filtered) {
1125 env->SetObjectArrayElement(ret, i, env->NewStringUTF(assureValidUTF8(module->renderText(results[i].c_str()))));
1126 }
1127 else {
1128 env->SetObjectArrayElement(ret, i, env->NewStringUTF(assureValidUTF8(results[i].c_str())));
1129 }
1130 }
1131 }
1132
1133 env->ReleaseStringUTFChars(level3JS, level3);
1134 env->ReleaseStringUTFChars(level2JS, level2);
1135 env->ReleaseStringUTFChars(level1JS, level1);
1136
1137 return (ret) ? ret : (jobjectArray) env->NewObjectArray(0, clazzString, NULL);
1138 }
1139
1140
1141 /*
1142 * Class: org_crosswire_android_sword_SWModule
1143 * Method: parseKeyList
1144 * Signature: (Ljava/lang/String;)[Ljava/lang/String;
1145 */
Java_org_crosswire_android_sword_SWModule_parseKeyList(JNIEnv * env,jobject me,jstring keyListTextJS)1146 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWModule_parseKeyList
1147 (JNIEnv *env, jobject me, jstring keyListTextJS) {
1148
1149 init(env);
1150
1151 const char *keyListText = env->GetStringUTFChars(keyListTextJS, NULL);
1152
1153 SWModule *module = getModule(env, me);
1154 jclass clazzString = env->FindClass("java/lang/String");
1155 jobjectArray ret;
1156
1157 if (module) {
1158 sword::SWKey *k = module->getKey();
1159 sword::VerseKey *parser = SWDYNAMIC_CAST(VerseKey, k);
1160 if (parser) {
1161 sword::ListKey result;
1162 result = parser->parseVerseList(keyListText, *parser, true);
1163 int count = 0;
1164 for (result = sword::TOP; !result.popError(); result++) {
1165 count++;
1166 }
1167 ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
1168
1169 count = 0;
1170 for (result = sword::TOP; !result.popError(); result++) {
1171 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8((const char *)result)));
1172 }
1173 }
1174 else {
1175 ret = (jobjectArray) env->NewObjectArray(1, clazzString, NULL);
1176 env->SetObjectArrayElement(ret, 0, env->NewStringUTF(assureValidUTF8(keyListText)));
1177 }
1178 }
1179
1180 env->ReleaseStringUTFChars(keyListTextJS, keyListText);
1181
1182 return ret;
1183 }
1184
1185
1186 /*
1187 * Class: org_crosswire_android_sword_SWModule
1188 * Method: hasKeyChildren
1189 * Signature: ()Z
1190 */
Java_org_crosswire_android_sword_SWModule_hasKeyChildren(JNIEnv * env,jobject me)1191 JNIEXPORT jboolean JNICALL Java_org_crosswire_android_sword_SWModule_hasKeyChildren
1192 (JNIEnv *env, jobject me) {
1193
1194 init(env);
1195
1196
1197 SWModule *module = getModule(env, me);
1198 jboolean retVal = JNI_FALSE;
1199
1200 if (module) {
1201 sword::SWKey *key = module->getKey();
1202
1203 TreeKeyIdx *tkey = SWDYNAMIC_CAST(TreeKeyIdx, key);
1204 if (tkey) {
1205 retVal = (tkey->hasChildren())?JNI_TRUE:JNI_FALSE;
1206 }
1207 }
1208 return retVal;
1209 }
1210
1211 /*
1212 * Class: org_crosswire_android_sword_SWModule
1213 * Method: getKeyChildren
1214 * Signature: ()[Ljava/lang/String;
1215 */
Java_org_crosswire_android_sword_SWModule_getKeyChildren(JNIEnv * env,jobject me)1216 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWModule_getKeyChildren
1217 (JNIEnv *env, jobject me) {
1218
1219 init(env);
1220
1221
1222 jclass clazzString = env->FindClass("java/lang/String");
1223 jobjectArray ret;
1224
1225 SWModule *module = getModule(env, me);
1226
1227 if (module) {
1228 sword::SWKey *key = module->getKey();
1229 int count = 0;
1230
1231 sword::VerseKey *vkey = SWDYNAMIC_CAST(VerseKey, key);
1232 if (vkey) {
1233 ret = (jobjectArray) env->NewObjectArray(10, clazzString, NULL);
1234 SWBuf num;
1235 num.appendFormatted("%d", vkey->getTestament());
1236 env->SetObjectArrayElement(ret, 0, env->NewStringUTF(assureValidUTF8(num.c_str())));
1237 num = "";
1238 num.appendFormatted("%d", vkey->getBook());
1239 env->SetObjectArrayElement(ret, 1, env->NewStringUTF(assureValidUTF8(num.c_str())));
1240 num = "";
1241 num.appendFormatted("%d", vkey->getChapter());
1242 env->SetObjectArrayElement(ret, 2, env->NewStringUTF(assureValidUTF8(num.c_str())));
1243 num = "";
1244 num.appendFormatted("%d", vkey->getVerse());
1245 env->SetObjectArrayElement(ret, 3, env->NewStringUTF(assureValidUTF8(num.c_str())));
1246 num = "";
1247 num.appendFormatted("%d", vkey->getChapterMax());
1248 env->SetObjectArrayElement(ret, 4, env->NewStringUTF(assureValidUTF8(num.c_str())));
1249 num = "";
1250 num.appendFormatted("%d", vkey->getVerseMax());
1251 env->SetObjectArrayElement(ret, 5, env->NewStringUTF(assureValidUTF8(num.c_str())));
1252 env->SetObjectArrayElement(ret, 6, env->NewStringUTF(assureValidUTF8(vkey->getBookName())));
1253 env->SetObjectArrayElement(ret, 7, env->NewStringUTF(assureValidUTF8(vkey->getOSISRef())));
1254 env->SetObjectArrayElement(ret, 8, env->NewStringUTF(assureValidUTF8(vkey->getShortText())));
1255 env->SetObjectArrayElement(ret, 9, env->NewStringUTF(assureValidUTF8(vkey->getBookAbbrev())));
1256 }
1257 else {
1258 TreeKeyIdx *tkey = SWDYNAMIC_CAST(TreeKeyIdx, key);
1259 if (tkey) {
1260 if (tkey->firstChild()) {
1261 do {
1262 count++;
1263 }
1264 while (tkey->nextSibling());
1265 tkey->parent();
1266 }
1267 ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
1268 count = 0;
1269 if (tkey->firstChild()) {
1270 do {
1271 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8(tkey->getLocalName())));
1272 }
1273 while (tkey->nextSibling());
1274 tkey->parent();
1275 }
1276 }
1277 }
1278 }
1279 return ret;
1280 }
1281
1282
1283 /*
1284 * Class: org_crosswire_android_sword_SWModule
1285 * Method: getKeyParent
1286 * Signature: ()Ljava/lang/String;
1287 */
Java_org_crosswire_android_sword_SWModule_getKeyParent(JNIEnv * env,jobject me)1288 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWModule_getKeyParent
1289 (JNIEnv *env, jobject me) {
1290
1291 init(env);
1292
1293
1294 SWBuf retVal = "";
1295
1296 SWModule *module = getModule(env, me);
1297
1298 if (module) {
1299
1300 sword::SWKey *key = module->getKey();
1301
1302 TreeKeyIdx *tkey = SWDYNAMIC_CAST(TreeKeyIdx, key);
1303 if (tkey) {
1304 if (tkey->parent()) {
1305 retVal = tkey->getText();
1306 }
1307 }
1308 }
1309 return env->NewStringUTF(assureValidUTF8(retVal));
1310 }
1311
1312
1313 /*
1314 * Class: org_crosswire_android_sword_SWModule
1315 * Method: previous
1316 * Signature: ()V
1317 */
Java_org_crosswire_android_sword_SWModule_previous(JNIEnv * env,jobject me)1318 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWModule_previous
1319 (JNIEnv *env, jobject me) {
1320
1321 init(env);
1322
1323
1324 SWModule *module = getModule(env, me);
1325
1326 if (module) {
1327 module->decrement();
1328 }
1329 }
1330
1331
1332 /*
1333 * Class: org_crosswire_android_sword_SWModule
1334 * Method: next
1335 * Signature: ()V
1336 */
Java_org_crosswire_android_sword_SWModule_next(JNIEnv * env,jobject me)1337 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWModule_next
1338 (JNIEnv *env, jobject me) {
1339
1340 init(env);
1341
1342
1343 SWModule *module = getModule(env, me);
1344
1345 if (module) {
1346 module->increment();
1347 }
1348 }
1349
1350
1351 /*
1352 * Class: org_crosswire_android_sword_SWModule
1353 * Method: begin
1354 * Signature: ()V
1355 */
Java_org_crosswire_android_sword_SWModule_begin(JNIEnv * env,jobject me)1356 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWModule_begin
1357 (JNIEnv *env, jobject me) {
1358
1359 init(env);
1360
1361
1362 SWModule *module = getModule(env, me);
1363
1364 if (module) {
1365 module->setPosition(sword::TOP);
1366 }
1367 }
1368
1369
1370 /*
1371 * Class: org_crosswire_android_sword_SWModule
1372 * Method: getStripText
1373 * Signature: ()Ljava/lang/String;
1374 */
Java_org_crosswire_android_sword_SWModule_getStripText(JNIEnv * env,jobject me)1375 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWModule_getStripText
1376 (JNIEnv *env, jobject me) {
1377
1378 init(env);
1379
1380
1381 SWBuf retVal = "";
1382
1383 SWModule *module = getModule(env, me);
1384
1385 if (module) {
1386 retVal = module->stripText();
1387 }
1388
1389 return env->NewStringUTF(assureValidUTF8(retVal));
1390 }
1391
1392
1393 /*
1394 * Class: org_crosswire_android_sword_SWModule
1395 * Method: getRawEntry
1396 * Signature: ()Ljava/lang/String;
1397 */
Java_org_crosswire_android_sword_SWModule_getRawEntry(JNIEnv * env,jobject me)1398 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWModule_getRawEntry
1399 (JNIEnv *env, jobject me) {
1400
1401 init(env);
1402
1403
1404 SWBuf retVal = "";
1405
1406 SWModule *module = getModule(env, me);
1407
1408 if (module) {
1409 retVal = module->getRawEntry();
1410 }
1411
1412 return env->NewStringUTF(assureValidUTF8(retVal));
1413 }
1414
1415
1416 /*
1417 * Class: org_crosswire_android_sword_SWModule
1418 * Method: setRawEntry
1419 * Signature: (Ljava/lang/String;)V
1420 */
Java_org_crosswire_android_sword_SWModule_setRawEntry(JNIEnv * env,jobject me,jstring newEntryTextJS)1421 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWModule_setRawEntry
1422 (JNIEnv *env, jobject me, jstring newEntryTextJS) {
1423
1424 init(env);
1425
1426
1427 const char *newEntryText = env->GetStringUTFChars(newEntryTextJS, NULL);
1428
1429 SWModule *module = getModule(env, me);
1430
1431 if (module) {
1432 module->setEntry(newEntryText);
1433 }
1434
1435 env->ReleaseStringUTFChars(newEntryTextJS, newEntryText);
1436 }
1437
1438
1439 /*
1440 * Class: org_crosswire_android_sword_SWModule
1441 * Method: getConfigEntry
1442 * Signature: (Ljava/lang/String;)Ljava/lang/String;
1443 */
Java_org_crosswire_android_sword_SWModule_getConfigEntry(JNIEnv * env,jobject me,jstring configKeyJS)1444 JNIEXPORT jstring JNICALL Java_org_crosswire_android_sword_SWModule_getConfigEntry
1445 (JNIEnv *env, jobject me, jstring configKeyJS) {
1446
1447 init(env);
1448
1449
1450 jstring retVal = 0;
1451
1452 const char *configKey = env->GetStringUTFChars(configKeyJS, NULL);
1453 SWLog::getSystemLog()->logDebug("getConfigEntry(%s)\n", configKey);
1454
1455 SWModule *module = getModule(env, me);
1456
1457 if (module) {
1458 SWBuf confValue = module->getConfigEntry(configKey);
1459 // special processing if we're requesting About-- kindof cheese
1460 if (!strcmp("About", configKey)) {
1461 RTFHTML().processText(confValue);
1462 }
1463 SWBuf assuredBuf = assureValidUTF8(confValue.c_str());
1464 retVal = env->NewStringUTF(assuredBuf.c_str());
1465 }
1466
1467 env->ReleaseStringUTFChars(configKeyJS, configKey);
1468
1469 return retVal;
1470 }
1471
1472
1473 /*
1474 * Class: org_crosswire_android_sword_SWModule
1475 * Method: deleteSearchFramework
1476 * Signature: ()V
1477 */
Java_org_crosswire_android_sword_SWModule_deleteSearchFramework(JNIEnv * env,jobject me)1478 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWModule_deleteSearchFramework
1479 (JNIEnv *env, jobject me) {
1480
1481 init(env);
1482
1483
1484 SWModule *module = getModule(env, me);
1485
1486 if (module) {
1487 module->deleteSearchFramework();
1488 }
1489 }
1490
1491
1492 /*
1493 * Class: org_crosswire_android_sword_SWModule
1494 * Method: hasSearchFramework
1495 * Signature: ()Z
1496 */
Java_org_crosswire_android_sword_SWModule_hasSearchFramework(JNIEnv * env,jobject me)1497 JNIEXPORT jboolean JNICALL Java_org_crosswire_android_sword_SWModule_hasSearchFramework
1498 (JNIEnv *env, jobject me) {
1499
1500 init(env);
1501
1502
1503 SWModule *module = getModule(env, me);
1504
1505 return (module && module->hasSearchFramework()) ? JNI_TRUE : JNI_FALSE;
1506 }
1507
1508
1509 struct pu {
pupu1510 pu(JNIEnv *env, jobject pr) : env(env), progressReporter(pr), last(0) {}
1511 JNIEnv *env;
1512 jobject progressReporter;
1513 char last;
1514 };
1515
1516
percentUpdate(char percent,void * userData)1517 void percentUpdate(char percent, void *userData) {
1518 struct pu *p = (struct pu *)userData;
1519
1520 // assert we've actually been given a progressReporter
1521 if (!p->progressReporter) return;
1522
1523 if (percent != p->last) {
1524 p->last = percent;
1525 jclass cls = p->env->GetObjectClass(p->progressReporter);
1526 jmethodID mid = p->env->GetMethodID(cls, "progressReport", "(I)V");
1527 if (mid != 0) {
1528 p->env->CallVoidMethod(p->progressReporter, mid, (jint)percent);
1529 }
1530 p->env->DeleteLocalRef(cls);
1531 }
1532 }
1533
1534
1535 /*
1536 * Class: org_crosswire_android_sword_SWModule
1537 * Method: search
1538 * Signature: (Ljava/lang/String;IJLjava/lang/String;Lorg/crosswire/android/sword/SWModule/SearchProgressReporter;)[Lorg/crosswire/android/sword/SWModule/SearchHit;
1539 */
Java_org_crosswire_android_sword_SWModule_search(JNIEnv * env,jobject me,jstring expressionJS,jint srchType,jlong flags,jstring scopeJS,jobject progressReporter)1540 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_SWModule_search
1541 (JNIEnv *env, jobject me, jstring expressionJS, jint srchType, jlong flags, jstring scopeJS, jobject progressReporter) {
1542
1543 init(env);
1544
1545 const int MAX_RETURN_COUNT = 999999;
1546
1547 const char *expression = env->GetStringUTFChars(expressionJS, NULL);
1548 const char *scope = scopeJS ? env->GetStringUTFChars(scopeJS, NULL) : 0;
1549
1550 jclass clazzSearchHit = env->FindClass("org/crosswire/android/sword/SWModule$SearchHit");
1551 jobjectArray ret = 0;
1552
1553 SWModule *module = getModule(env, me);
1554
1555 // TODO: remove this from the stack
1556 pu *peeuuu = new pu(env, progressReporter);
1557
1558 if (module) {
1559 sword::ListKey lscope;
1560 sword::ListKey result;
1561
1562 if ((scope) && (strlen(scope)) > 0) {
1563 sword::SWKey *p = module->createKey();
1564 sword::VerseKey *parser = SWDYNAMIC_CAST(VerseKey, p);
1565 if (!parser) {
1566 delete p;
1567 parser = new VerseKey();
1568 }
1569 *parser = module->getKeyText();
1570 lscope = parser->parseVerseList(scope, *parser, true);
1571 result = module->search(expression, srchType, flags, &lscope, 0, &percentUpdate, peeuuu);
1572 delete parser;
1573 }
1574 else result = module->search(expression, srchType, flags, 0, 0, &percentUpdate, peeuuu);
1575
1576 delete peeuuu;
1577
1578 int count = 0;
1579 for (result = sword::TOP; !result.popError(); result++) count++;
1580
1581 if (count > MAX_RETURN_COUNT) count = MAX_RETURN_COUNT;
1582
1583 ret = (jobjectArray) env->NewObjectArray(count, clazzSearchHit, NULL);
1584
1585 // if we're sorted by score, let's re-sort by verse, because Java can always re-sort by score
1586 result = sword::TOP;
1587 if ((count) && (long)result.getElement()->userData)
1588 result.sort();
1589
1590 int i = 0;
1591 jstring modName = env->NewStringUTF(assureValidUTF8(module->getName()));
1592 jfieldID fieldIDModName = env->GetFieldID(clazzSearchHit, "modName", "Ljava/lang/String;");
1593 jfieldID fieldIDKey = env->GetFieldID(clazzSearchHit, "key" , "Ljava/lang/String;");
1594 jfieldID fieldIDScore = env->GetFieldID(clazzSearchHit, "score" , "J");
1595 for (result = sword::TOP; !result.popError(); result++) {
1596 jfieldID fieldID;
1597 jobject searchHit = env->AllocObject(clazzSearchHit);
1598
1599 env->SetObjectField(searchHit, fieldIDModName, modName);
1600 jstring key = env->NewStringUTF(assureValidUTF8((const char *)result));
1601 env->SetObjectField(searchHit, fieldIDKey, key);
1602 env->DeleteLocalRef(key);
1603 env->SetLongField(searchHit, fieldIDScore, (long)result.getElement()->userData);
1604
1605 env->SetObjectArrayElement(ret, i++, searchHit);
1606 env->DeleteLocalRef(searchHit);
1607 if (i >= MAX_RETURN_COUNT) break;
1608 }
1609 env->DeleteLocalRef(modName);
1610 }
1611
1612 if (scope) env->ReleaseStringUTFChars(scopeJS, scope);
1613 env->ReleaseStringUTFChars(expressionJS, expression);
1614
1615 return (ret) ? ret : (jobjectArray) env->NewObjectArray(0, clazzSearchHit, NULL);
1616 }
1617
1618
1619
1620 // InstallMgr methods ----------------------------------------------------------------------------------
1621
1622
1623 /*
1624 * Class: org_crosswire_android_sword_InstallMgr
1625 * Method: reInit
1626 * Signature: ()V
1627 */
Java_org_crosswire_android_sword_InstallMgr_reInit(JNIEnv * env,jobject me)1628 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_InstallMgr_reInit
1629 (JNIEnv *env, jobject me) {
1630
1631 delete installMgr;
1632 installMgr = 0;
1633 }
1634
1635
1636 /*
1637 * Class: org_crosswire_android_sword_InstallMgr
1638 * Method: syncConfig
1639 * Signature: ()I
1640 */
Java_org_crosswire_android_sword_InstallMgr_syncConfig(JNIEnv * env,jobject me)1641 JNIEXPORT jint JNICALL Java_org_crosswire_android_sword_InstallMgr_syncConfig
1642 (JNIEnv *env, jobject me) {
1643
1644 initInstall(env);
1645
1646 return installMgr->refreshRemoteSourceConfiguration();
1647 }
1648
1649
1650 /*
1651 * Class: org_crosswire_android_sword_InstallMgr
1652 * Method: uninstallModule
1653 * Signature: (Ljava/lang/String;)I
1654 */
Java_org_crosswire_android_sword_InstallMgr_uninstallModule(JNIEnv * env,jobject me,jstring modNameJS)1655 JNIEXPORT jint JNICALL Java_org_crosswire_android_sword_InstallMgr_uninstallModule
1656 (JNIEnv *env, jobject me, jstring modNameJS) {
1657
1658 init(env);
1659 initInstall(env);
1660
1661 const char *modName = env->GetStringUTFChars(modNameJS, NULL);
1662
1663 SWLog::getSystemLog()->logDebug("uninstallModule %s\n", modName);
1664
1665 SWModule *module;
1666 ModMap::iterator it = mgr->Modules.find(modName);
1667 if (it == mgr->Modules.end()) {
1668 return -2;
1669 }
1670 module = it->second;
1671 int retVal = installMgr->removeModule(mgr, module->getName());
1672
1673 env->ReleaseStringUTFChars(modNameJS, modName);
1674
1675 return retVal;
1676 }
1677
1678
1679 /*
1680 * Class: org_crosswire_android_sword_InstallMgr
1681 * Method: getRemoteSources
1682 * Signature: ()[Ljava/lang/String;
1683 */
Java_org_crosswire_android_sword_InstallMgr_getRemoteSources(JNIEnv * env,jobject me)1684 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_InstallMgr_getRemoteSources
1685 (JNIEnv *env, jobject me) {
1686
1687 initInstall(env);
1688
1689 jclass clazzString = env->FindClass("java/lang/String");
1690 jobjectArray ret;
1691
1692 int count = 0;
1693 for (InstallSourceMap::iterator it = installMgr->sources.begin(); it != installMgr->sources.end(); ++it) {
1694 count++;
1695 }
1696 SWLog::getSystemLog()->logDebug("getRemoteSources: count: %d\n", count);
1697 ret = (jobjectArray) env->NewObjectArray(count, clazzString, NULL);
1698 count = 0;
1699 for (InstallSourceMap::iterator it = installMgr->sources.begin(); it != installMgr->sources.end(); ++it) {
1700 env->SetObjectArrayElement(ret, count++, env->NewStringUTF(assureValidUTF8(it->second->caption.c_str())));
1701 }
1702
1703 return ret;
1704 }
1705
1706
1707 /*
1708 * Class: org_crosswire_android_sword_InstallMgr
1709 * Method: refreshRemoteSource
1710 * Signature: (Ljava/lang/String;)I
1711 */
Java_org_crosswire_android_sword_InstallMgr_refreshRemoteSource(JNIEnv * env,jobject me,jstring sourceNameJS)1712 JNIEXPORT jint JNICALL Java_org_crosswire_android_sword_InstallMgr_refreshRemoteSource
1713 (JNIEnv *env, jobject me, jstring sourceNameJS) {
1714
1715 initInstall(env);
1716
1717 const char *sourceName = env->GetStringUTFChars(sourceNameJS, NULL);
1718
1719 InstallSourceMap::iterator source = installMgr->sources.find(sourceName);
1720 if (source == installMgr->sources.end()) {
1721 return -3;
1722 }
1723
1724 env->ReleaseStringUTFChars(sourceNameJS, sourceName);
1725
1726 return installMgr->refreshRemoteSource(source->second);
1727 }
1728
1729
1730 /*
1731 * Class: org_crosswire_android_sword_InstallMgr
1732 * Method: getRemoteModInfoList
1733 * Signature: (Ljava/lang/String;)[Lorg/crosswire/android/sword/SWMgr/ModInfo;
1734 */
Java_org_crosswire_android_sword_InstallMgr_getRemoteModInfoList(JNIEnv * env,jobject me,jstring sourceNameJS)1735 JNIEXPORT jobjectArray JNICALL Java_org_crosswire_android_sword_InstallMgr_getRemoteModInfoList
1736 (JNIEnv *env, jobject me, jstring sourceNameJS) {
1737
1738 SWLog::getSystemLog()->logDebug("getRemoteModInfoList\n");
1739 init(env);
1740 initInstall(env);
1741
1742 const char *sourceName = env->GetStringUTFChars(sourceNameJS, NULL);
1743 SWLog::getSystemLog()->logDebug("sourceName: %s\n", sourceName);
1744
1745 jclass clazzModInfo = env->FindClass("org/crosswire/android/sword/SWMgr$ModInfo");
1746 jfieldID nameID = env->GetFieldID(clazzModInfo, "name", "Ljava/lang/String;");
1747 jfieldID descID = env->GetFieldID(clazzModInfo, "description", "Ljava/lang/String;");
1748 jfieldID catID = env->GetFieldID(clazzModInfo, "category", "Ljava/lang/String;");
1749 jfieldID langID = env->GetFieldID(clazzModInfo, "language", "Ljava/lang/String;");
1750 jfieldID versionID = env->GetFieldID(clazzModInfo, "version", "Ljava/lang/String;");
1751 jfieldID deltaID = env->GetFieldID(clazzModInfo, "delta", "Ljava/lang/String;");
1752
1753 InstallSourceMap::iterator source = installMgr->sources.find(sourceName);
1754 if (source == installMgr->sources.end()) {
1755 SWLog::getSystemLog()->logDebug("remoteListModules returning 0 length array\n");
1756 return (jobjectArray) env->NewObjectArray(0, clazzModInfo, NULL);
1757 }
1758 SWLog::getSystemLog()->logDebug("found source: %s\n", sourceName);
1759
1760 map<SWModule *, int> modStats = installMgr->getModuleStatus(*mgr, *source->second->getMgr());
1761
1762 int size = 0;
1763 for (map<SWModule *, int>::iterator it = modStats.begin(); it != modStats.end(); ++it) {
1764 size++;
1765 }
1766
1767 SWLog::getSystemLog()->logDebug("remoteListModules returning %d length array\n", size);
1768 jobjectArray ret = (jobjectArray) env->NewObjectArray(size, clazzModInfo, NULL);
1769
1770 int i = 0;
1771 for (map<SWModule *, int>::iterator it = modStats.begin(); it != modStats.end(); ++it) {
1772 SWModule *module = it->first;
1773 int status = it->second;
1774
1775 SWBuf version = module->getConfigEntry("Version");
1776 SWBuf statusString = " ";
1777 if (status & InstallMgr::MODSTAT_NEW) statusString = "*";
1778 if (status & InstallMgr::MODSTAT_OLDER) statusString = "-";
1779 if (status & InstallMgr::MODSTAT_UPDATED) statusString = "+";
1780
1781 SWBuf type = module->getType();
1782 SWBuf cat = module->getConfigEntry("Category");
1783 if (cat.length() > 0) type = cat;
1784 jobject modInfo = env->AllocObject(clazzModInfo);
1785
1786 jstring val;
1787 val = env->NewStringUTF(assureValidUTF8(module->getName())); env->SetObjectField(modInfo, nameID , val); env->DeleteLocalRef(val);
1788 val = env->NewStringUTF(assureValidUTF8(module->getDescription())); env->SetObjectField(modInfo, descID , val); env->DeleteLocalRef(val);
1789 val = env->NewStringUTF(assureValidUTF8(type.c_str())); env->SetObjectField(modInfo, catID , val); env->DeleteLocalRef(val);
1790 val = env->NewStringUTF(assureValidUTF8(module->getLanguage())); env->SetObjectField(modInfo, langID , val); env->DeleteLocalRef(val);
1791 val = env->NewStringUTF(assureValidUTF8(version.c_str())); env->SetObjectField(modInfo, versionID, val); env->DeleteLocalRef(val);
1792 val = env->NewStringUTF(assureValidUTF8(statusString.c_str())); env->SetObjectField(modInfo, deltaID , val); env->DeleteLocalRef(val);
1793
1794 env->SetObjectArrayElement(ret, i++, modInfo);
1795
1796 env->DeleteLocalRef(modInfo);
1797 }
1798
1799 env->ReleaseStringUTFChars(sourceNameJS, sourceName);
1800
1801 return ret;
1802 }
1803
1804 /*
1805 * Class: org_crosswire_android_sword_InstallMgr
1806 * Method: remoteInstallModule
1807 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
1808 */
Java_org_crosswire_android_sword_InstallMgr_remoteInstallModule(JNIEnv * env,jobject me,jstring sourceNameJS,jstring modNameJS,jobject progressReporter)1809 JNIEXPORT jint JNICALL Java_org_crosswire_android_sword_InstallMgr_remoteInstallModule
1810 (JNIEnv *env, jobject me, jstring sourceNameJS, jstring modNameJS, jobject progressReporter) {
1811
1812 init(env);
1813 initInstall(env, progressReporter);
1814
1815 const char *sourceName = env->GetStringUTFChars(sourceNameJS, NULL);
1816 SWLog::getSystemLog()->logDebug("remoteInstallModule: sourceName: %s\n", sourceName);
1817 InstallSourceMap::iterator source = installMgr->sources.find(sourceName);
1818 env->ReleaseStringUTFChars(sourceNameJS, sourceName);
1819
1820 if (source == installMgr->sources.end()) {
1821 return -3;
1822 }
1823
1824 InstallSource *is = source->second;
1825 SWMgr *rmgr = is->getMgr();
1826 SWModule *module;
1827
1828 const char *modName = env->GetStringUTFChars(modNameJS, NULL);
1829 SWLog::getSystemLog()->logDebug("remoteInstallModule: modName: %s\n", modName);
1830 ModMap::iterator it = rmgr->Modules.find(modName);
1831 env->ReleaseStringUTFChars(modNameJS, modName);
1832
1833 if (it == rmgr->Modules.end()) {
1834 return -4;
1835 }
1836
1837 module = it->second;
1838
1839 int error = installMgr->installModule(mgr, 0, module->getName(), is);
1840
1841 if (progressReporter) {
1842 jclass cls = env->GetObjectClass(progressReporter);
1843 jmethodID mid = env->GetMethodID(cls, "preStatus", "(JJLjava/lang/String;)V");
1844 if (mid != 0) {
1845 jstring msg = env->NewStringUTF("Complete");
1846 env->CallVoidMethod(progressReporter, mid, (jlong)0, (jlong)0, msg);
1847 env->DeleteLocalRef(msg);
1848 }
1849 env->DeleteLocalRef(cls);
1850 }
1851
1852 return error;
1853 }
1854
1855
1856 /*
1857 * Class: org_crosswire_android_sword_InstallMgr
1858 * Method: getRemoteModuleByName
1859 * Signature: (Ljava/lang/String;Ljava/lang/String;)Lorg/crosswire/android/sword/SWModule;
1860 */
Java_org_crosswire_android_sword_InstallMgr_getRemoteModuleByName(JNIEnv * env,jobject me,jstring sourceNameJS,jstring modNameJS)1861 JNIEXPORT jobject JNICALL Java_org_crosswire_android_sword_InstallMgr_getRemoteModuleByName
1862 (JNIEnv *env, jobject me, jstring sourceNameJS, jstring modNameJS) {
1863
1864 jobject retVal = 0;
1865
1866 initInstall(env);
1867
1868 const char *sourceName = env->GetStringUTFChars(sourceNameJS, NULL);
1869 SWLog::getSystemLog()->logDebug("getRemoteModuleByName: sourceName: %s\n", sourceName);
1870 InstallSourceMap::iterator source = installMgr->sources.find(sourceName);
1871 env->ReleaseStringUTFChars(sourceNameJS, sourceName);
1872
1873 if (source == installMgr->sources.end()) {
1874 SWLog::getSystemLog()->logDebug("Couldn't find remote source [%s]\n", sourceName);
1875 return 0;
1876 }
1877
1878 SWMgr *mgr = source->second->getMgr();
1879
1880 const char *modName = env->GetStringUTFChars(modNameJS, NULL);
1881 sword::SWModule *module = mgr->getModule(modName);
1882 env->ReleaseStringUTFChars(modNameJS, modName);
1883
1884 if (module) {
1885 SWBuf type = module->getType();
1886 SWBuf cat = module->getConfigEntry("Category");
1887 if (cat.length() > 0) type = cat;
1888 jfieldID fieldID;
1889 jclass clazzSWModule = env->FindClass("org/crosswire/android/sword/SWModule");
1890 retVal = env->AllocObject(clazzSWModule);
1891 fieldID = env->GetFieldID(clazzSWModule, "name", "Ljava/lang/String;"); env->SetObjectField(retVal, fieldID, env->NewStringUTF(assureValidUTF8(module->getName())));
1892 fieldID = env->GetFieldID(clazzSWModule, "description", "Ljava/lang/String;"); env->SetObjectField(retVal, fieldID, env->NewStringUTF(assureValidUTF8(module->getDescription())));
1893 fieldID = env->GetFieldID(clazzSWModule, "category", "Ljava/lang/String;"); env->SetObjectField(retVal, fieldID, env->NewStringUTF(assureValidUTF8(type.c_str())));
1894 fieldID = env->GetFieldID(clazzSWModule, "remoteSourceName", "Ljava/lang/String;"); env->SetObjectField(retVal, fieldID, sourceNameJS);
1895 }
1896
1897 return retVal;
1898
1899 }
1900
1901
1902 /*
1903 * Class: org_crosswire_android_sword_InstallMgr
1904 * Method: setUserDisclaimerConfirmed
1905 * Signature: ()V
1906 */
Java_org_crosswire_android_sword_InstallMgr_setUserDisclaimerConfirmed(JNIEnv * env,jobject me)1907 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_InstallMgr_setUserDisclaimerConfirmed
1908 (JNIEnv *env, jobject me) {
1909
1910 initInstall(env);
1911
1912 disclaimerConfirmed = true;
1913 installMgr->setUserDisclaimerConfirmed(true);
1914 }
1915
1916
1917 /*
1918 * Class: org_crosswire_android_sword_SWMgr
1919 * Method: sendBibleSyncMessage
1920 * Signature: (Ljava/lang/String;)V
1921 */
Java_org_crosswire_android_sword_SWMgr_sendBibleSyncMessage(JNIEnv * env,jobject me,jstring osisRefJS)1922 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_sendBibleSyncMessage
1923 (JNIEnv *env, jobject me, jstring osisRefJS) {
1924
1925 initBibleSync();
1926 const char *osisRef = env->GetStringUTFChars(osisRefJS, NULL);
1927
1928 #ifdef BIBLESYNC
1929 BibleSync_xmit_status retval = bibleSync->Transmit(BSP_SYNC, "Bible", osisRef);
1930 #endif
1931
1932 env->ReleaseStringUTFChars(osisRefJS, osisRef);
1933 }
1934
1935
1936 /*
1937 * NOTE: this method blocks and should be called in a new thread
1938 * Class: org_crosswire_android_sword_SWMgr
1939 * Method: registerBibleSyncListener
1940 * Signature: (Ljava/lang/Object;)V
1941 */
Java_org_crosswire_android_sword_SWMgr_registerBibleSyncListener(JNIEnv * env,jobject me,jobject bibleSyncListener)1942 JNIEXPORT void JNICALL Java_org_crosswire_android_sword_SWMgr_registerBibleSyncListener
1943 (JNIEnv *env, jobject me, jobject bibleSyncListener) {
1944
1945 #ifdef BIBLESYNC
1946 SWLog::getSystemLog()->logDebug("registerBibleSyncListener");
1947 ::bibleSyncListener = bibleSyncListener;
1948 ::bibleSyncListenerEnv = env;
1949 SWLog::getSystemLog()->logDebug("registerBibleSyncListener - calling init");
1950 initBibleSync();
1951 SWLog::getSystemLog()->logDebug("registerBibleSyncListener - starting while listener");
1952 while(::bibleSyncListener) {
1953 SWLog::getSystemLog()->logDebug("bibleSyncListener - while loop iteration");
1954 BibleSync::Receive(bibleSync);
1955 SWLog::getSystemLog()->logDebug("bibleSyncListener - sleeping for 2 seconds");
1956 sleep(2);
1957 }
1958 #endif
1959 }
1960
1961