1717
1818namespace {
1919
20- std::string convertString (JNIEnv *env, jstring string) {
21- jboolean isCopy;
22- const char *cstring = env->GetStringUTFChars (string, &isCopy);
23- auto cppstring = std::string (cstring, env->GetStringUTFLength (string));
24- env->ReleaseStringUTFChars (string, cstring);
25- return cppstring;
26- }
20+ std::string convertString (JNIEnv *env, jstring string) {
21+ jboolean isCopy;
22+ const char *cstring = env->GetStringUTFChars (string, &isCopy);
23+ auto cppstring = std::string (cstring, env->GetStringUTFLength (string));
24+ env->ReleaseStringUTFChars (string, cstring);
25+ return cppstring;
26+ }
2727
28- std::string getStringField (JNIEnv *env, jclass clazz, jobject object, const char *name) {
29- jfieldID field = env->GetFieldID (clazz, name, " Ljava/lang/String;" );
30- auto string = (jstring) env->GetObjectField (object, field);
31- return convertString (env, string);
32- }
28+ std::string getStringField (JNIEnv *env, jclass clazz, jobject object, const char *name) {
29+ jfieldID field = env->GetFieldID (clazz, name, " Ljava/lang/String;" );
30+ auto string = (jstring) env->GetObjectField (object, field);
31+ return convertString (env, string);
32+ }
3333
34- std::string getStringField (JNIEnv *env, jobject object, const char *name) {
35- jclass clazz = env->GetObjectClass (object);
36- return getStringField (env, clazz, object, name);
37- }
34+ std::string getStringField (JNIEnv *env, jobject object, const char *name) {
35+ jclass clazz = env->GetObjectClass (object);
36+ return getStringField (env, clazz, object, name);
37+ }
3838
39- class AndroidLogger final : public odr::Logger {
40- public:
41- static int to_android_log_level (odr::LogLevel level) {
42- switch (level) {
43- case odr::LogLevel::verbose:
44- return ANDROID_LOG_VERBOSE;
45- case odr::LogLevel::debug:
46- return ANDROID_LOG_DEBUG;
47- case odr::LogLevel::info:
48- return ANDROID_LOG_INFO;
49- case odr::LogLevel::warning:
50- return ANDROID_LOG_WARN;
51- case odr::LogLevel::error:
52- return ANDROID_LOG_ERROR;
53- case odr::LogLevel::fatal:
54- return ANDROID_LOG_FATAL;
55- default :
56- return ANDROID_LOG_UNKNOWN;
39+ class AndroidLogger final : public odr::Logger {
40+ public:
41+ static int to_android_log_level (odr::LogLevel level) {
42+ switch (level) {
43+ case odr::LogLevel::verbose:
44+ return ANDROID_LOG_VERBOSE;
45+ case odr::LogLevel::debug:
46+ return ANDROID_LOG_DEBUG;
47+ case odr::LogLevel::info:
48+ return ANDROID_LOG_INFO;
49+ case odr::LogLevel::warning:
50+ return ANDROID_LOG_WARN;
51+ case odr::LogLevel::error:
52+ return ANDROID_LOG_ERROR;
53+ case odr::LogLevel::fatal:
54+ return ANDROID_LOG_FATAL;
55+ default :
56+ return ANDROID_LOG_UNKNOWN;
57+ }
5758 }
58- }
5959
60- void flush () override {}
60+ void flush () override {}
6161
62- [[nodiscard]] bool will_log (odr::LogLevel level) const override {
63- return true ;
64- }
62+ [[nodiscard]] bool will_log (odr::LogLevel level) const override {
63+ return true ;
64+ }
6565
66- protected:
67- void log_impl (Time time, odr::LogLevel level, const std::string &message,
68- const std::source_location &location) override {
69- __android_log_print (to_android_log_level (level), " smn" , " %s" , message.c_str ());
70- }
66+ protected:
67+ void log_impl (Time time, odr::LogLevel level, const std::string &message,
68+ const std::source_location &location) override {
69+ __android_log_print (to_android_log_level (level), " smn" , " %s" , message.c_str ());
70+ }
7171
72- private:
72+ private:
7373
74- };
74+ };
7575
7676}
7777
@@ -300,7 +300,7 @@ std::optional<odr::HttpServer> s_server;
300300
301301JNIEXPORT void JNICALL
302302Java_at_tomtasche_reader_background_CoreWrapper_createServerNative (JNIEnv *env, jclass clazz,
303- jstring cachePath) {
303+ jstring cachePath) {
304304 __android_log_print (ANDROID_LOG_INFO, " smn" , " create server" );
305305
306306 std::string cachePathCpp = convertString (env, cachePath);
@@ -313,8 +313,9 @@ Java_at_tomtasche_reader_background_CoreWrapper_createServerNative(JNIEnv *env,
313313}
314314
315315JNIEXPORT jobject JNICALL
316- Java_at_tomtasche_reader_background_CoreWrapper_hostFileNative (JNIEnv *env, jclass clazz, jstring prefix,
317- jobject options) {
316+ Java_at_tomtasche_reader_background_CoreWrapper_hostFileNative (JNIEnv *env, jclass clazz,
317+ jstring prefix,
318+ jobject options) {
318319 __android_log_print (ANDROID_LOG_INFO, " smn" , " host file" );
319320
320321 auto logger = std::make_shared<AndroidLogger>();
@@ -330,117 +331,129 @@ Java_at_tomtasche_reader_background_CoreWrapper_hostFileNative(JNIEnv *env, jcla
330331 return result;
331332 }
332333
333- s_server->clear ();
334-
335- jclass optionsClass = env->GetObjectClass (options);
334+ try {
335+ s_server->clear ();
336336
337- std::optional<std::string> passwordCpp;
338- jfieldID passwordField = env->GetFieldID (optionsClass, " password" , " Ljava/lang/String;" );
339- auto password = (jstring) env->GetObjectField (options, passwordField);
340- if (password != nullptr ) {
341- passwordCpp = convertString (env, password);
342- }
337+ jclass optionsClass = env->GetObjectClass (options);
343338
344- jfieldID pagingField = env->GetFieldID (optionsClass, " paging" , " Z" );
345- jboolean paging = env->GetBooleanField (options, pagingField);
339+ std::optional<std::string> passwordCpp;
340+ jfieldID passwordField = env->GetFieldID (optionsClass, " password" , " Ljava/lang/String;" );
341+ auto password = (jstring) env->GetObjectField (options, passwordField);
342+ if (password != nullptr ) {
343+ passwordCpp = convertString (env, password);
344+ }
346345
347- jfieldID editableField = env->GetFieldID (optionsClass, " editable " , " Z" );
348- jboolean editable = env->GetBooleanField (options, editableField );
346+ jfieldID pagingField = env->GetFieldID (optionsClass, " paging " , " Z" );
347+ jboolean paging = env->GetBooleanField (options, pagingField );
349348
350- std::string outputPathCpp = getStringField (env, optionsClass, options, " outputPath" );
349+ jfieldID editableField = env->GetFieldID (optionsClass, " editable" , " Z" );
350+ jboolean editable = env->GetBooleanField (options, editableField);
351351
352- jclass listClass = env->FindClass (" java/util/List" );
353- jmethodID addMethod = env->GetMethodID (listClass, " add" , " (Ljava/lang/Object;)Z" );
352+ std::string outputPathCpp = getStringField (env, optionsClass, options, " outputPath" );
354353
355- jfieldID pageNamesField = env->GetFieldID (resultClass, " pageNames " , " Ljava /util/List; " );
356- auto pageNames = (jobject) env->GetObjectField (result, pageNamesField );
354+ jclass listClass = env->FindClass ( " java /util/List" );
355+ jmethodID addMethod = env->GetMethodID (listClass, " add " , " (Ljava/lang/Object;)Z " );
357356
358- jfieldID pagePathsField = env->GetFieldID (resultClass, " pagePaths " , " Ljava/util/List;" );
359- auto pagePaths = (jobject) env->GetObjectField (result, pagePathsField );
357+ jfieldID pageNamesField = env->GetFieldID (resultClass, " pageNames " , " Ljava/util/List;" );
358+ auto pageNames = (jobject) env->GetObjectField (result, pageNamesField );
360359
361- std::string inputPathCpp = getStringField ( env, options , " inputPath " );
362- std::string prefixCpp = convertString ( env, prefix );
360+ jfieldID pagePathsField = env-> GetFieldID (resultClass, " pagePaths " , " Ljava/util/List; " );
361+ auto pagePaths = (jobject) env-> GetObjectField (result, pagePathsField );
363362
364- odr::DecodePreference decodePreference;
365- decodePreference.engine_priority = {odr::DecoderEngine::poppler, odr::DecoderEngine::wvware,
366- odr::DecoderEngine::odr};
367- odr::DecodedFile file = odr::open (inputPathCpp, decodePreference, *logger);
363+ std::string inputPathCpp = getStringField (env, options, " inputPath" );
364+ std::string prefixCpp = convertString (env, prefix);
368365
369- if (file.password_encrypted ()) {
370- if (!passwordCpp.has_value ()) {
371- env->SetIntField (result, errorField, -2 );
372- return result;
373- }
374366 try {
375- file = file.decrypt (passwordCpp.value ());
376- } catch (...) {
377- env->SetIntField (result, errorField, -2 );
378- return result;
379- }
380- }
381-
382- if (file.is_document_file ()) {
383- // TODO this will cause a second load
384- s_document = file.as_document_file ().document ();
385- }
367+ odr::DecodePreference decodePreference;
368+ decodePreference.engine_priority = {odr::DecoderEngine::poppler,
369+ odr::DecoderEngine::wvware,
370+ odr::DecoderEngine::odr};
371+ odr::DecodedFile file = odr::open (inputPathCpp, decodePreference, *logger);
386372
387- odr::HtmlConfig htmlConfig;
388- htmlConfig.embed_images = false ;
389- htmlConfig.embed_shipped_resources = true ;
390- htmlConfig.relative_resource_paths = false ;
391- htmlConfig.text_document_margin = paging;
392- htmlConfig.editable = editable;
373+ if (file.password_encrypted ()) {
374+ if (!passwordCpp.has_value ()) {
375+ env->SetIntField (result, errorField, -2 );
376+ return result;
377+ }
378+ try {
379+ file = file.decrypt (passwordCpp.value ());
380+ } catch (...) {
381+ env->SetIntField (result, errorField, -2 );
382+ return result;
383+ }
384+ }
393385
394- try {
395- std::string output_tmp = outputPathCpp + " /tmp" ;
396- std::filesystem::create_directories (output_tmp);
397- odr::HtmlService service = odr::html::translate (file, output_tmp, htmlConfig, logger);
398- s_server->connect_service (service, prefixCpp);
399- odr::HtmlViews htmlViews = service.list_views ();
400-
401- for (const auto &view: htmlViews) {
402- __android_log_print (ANDROID_LOG_INFO, " smn" , " view name=%s path=%s" , view.name ().c_str (), view.path ().c_str ());
403- if (file.is_document_file () && (
404- (((file.as_document_file ().document_type () == odr::DocumentType::presentation) ||
405- (file.as_document_file ().document_type () == odr::DocumentType::drawing)) &&
406- (view.name () != " document" )) ||
407- ((file.as_document_file ().document_type () == odr::DocumentType::spreadsheet) &&
408- (view.name () == " document" )))) {
409- continue ;
386+ if (file.is_document_file ()) {
387+ // TODO this will cause a second load
388+ s_document = file.as_document_file ().document ();
410389 }
411390
412- jstring pageName = env->NewStringUTF (view.name ().c_str ());
413- env->CallBooleanMethod (pageNames, addMethod, pageName);
391+ odr::HtmlConfig htmlConfig;
392+ htmlConfig.embed_images = false ;
393+ htmlConfig.embed_shipped_resources = true ;
394+ htmlConfig.relative_resource_paths = false ;
395+ htmlConfig.text_document_margin = paging;
396+ htmlConfig.editable = editable;
397+
398+ std::string output_tmp = outputPathCpp + " /tmp" ;
399+ std::filesystem::create_directories (output_tmp);
400+ odr::HtmlService service = odr::html::translate (file, output_tmp, htmlConfig, logger);
401+ s_server->connect_service (service, prefixCpp);
402+ odr::HtmlViews htmlViews = service.list_views ();
403+
404+ for (const auto &view: htmlViews) {
405+ __android_log_print (ANDROID_LOG_INFO, " smn" , " view name=%s path=%s" ,
406+ view.name ().c_str (), view.path ().c_str ());
407+ if (file.is_document_file () && (
408+ (((file.as_document_file ().document_type () ==
409+ odr::DocumentType::presentation) ||
410+ (file.as_document_file ().document_type () ==
411+ odr::DocumentType::drawing)) &&
412+ (view.name () != " document" )) ||
413+ ((file.as_document_file ().document_type () ==
414+ odr::DocumentType::spreadsheet) &&
415+ (view.name () == " document" )))) {
416+ continue ;
417+ }
418+
419+ jstring pageName = env->NewStringUTF (view.name ().c_str ());
420+ env->CallBooleanMethod (pageNames, addMethod, pageName);
414421
415- std::string pagePathCpp =
416- " http://localhost:29665/file/" + prefixCpp + " /" + view.path ();
417- jstring pagePath = env->NewStringUTF (pagePathCpp.c_str ());
418- env->CallBooleanMethod (pagePaths, addMethod, pagePath);
422+ std::string pagePathCpp =
423+ " http://localhost:29665/file/" + prefixCpp + " /" + view.path ();
424+ jstring pagePath = env->NewStringUTF (pagePathCpp.c_str ());
425+ env->CallBooleanMethod (pagePaths, addMethod, pagePath);
426+ }
427+ } catch (const odr::UnknownFileType &e) {
428+ __android_log_print (ANDROID_LOG_ERROR, " smn" , " Unknown file type: %s" , e.what ());
429+ env->SetIntField (result, errorField, -5 );
430+ return result;
431+ } catch (const odr::UnsupportedFileType &e) {
432+ __android_log_print (ANDROID_LOG_ERROR, " smn" , " Unsupported file type: %s" , e.what ());
433+ env->SetIntField (result, errorField, -5 );
434+ return result;
435+ } catch (const std::exception &e) {
436+ __android_log_print (ANDROID_LOG_ERROR, " smn" , " Unhandled C++ exception: %s" , e.what ());
437+ env->SetIntField (result, errorField, -4 );
438+ return result;
439+ } catch (...) {
440+ __android_log_print (ANDROID_LOG_ERROR, " smn" ,
441+ " Unhandled C++ exception without further information" );
442+ env->SetIntField (result, errorField, -4 );
443+ return result;
419444 }
420- } catch (const std::exception &e) {
421- __android_log_print (ANDROID_LOG_ERROR, " smn" , " Unhandled C++ exception: %s" , e.what ());
422- env->SetIntField (result, errorField, -1 );
423- return result;
424- } catch (const std::string &s) {
425- __android_log_print (ANDROID_LOG_ERROR, " smn" , " Unhandled C++ string exception: %s" , s.c_str ());
426- env->SetIntField (result, errorField, -1 );
427- return result;
428- } catch (int i) {
429- __android_log_print (ANDROID_LOG_ERROR, " smn" , " Unhandled C++ int exception: %i" , i);
430- env->SetIntField (result, errorField, -1 );
431- return result;
432445 } catch (...) {
433- __android_log_print (ANDROID_LOG_ERROR, " smn" ,
434- " Unhandled C++ exception without further information" );
435- env->SetIntField (result, errorField, -1 );
446+ env->SetIntField (result, errorField, -3 );
436447 return result;
437448 }
438449
450+ env->SetIntField (result, errorField, 0 );
439451 return result;
440452}
441453
442454JNIEXPORT void JNICALL
443- Java_at_tomtasche_reader_background_CoreWrapper_listenServerNative (JNIEnv *env, jclass clazz, jint port) {
455+ Java_at_tomtasche_reader_background_CoreWrapper_listenServerNative (JNIEnv *env, jclass clazz,
456+ jint port) {
444457 __android_log_print (ANDROID_LOG_INFO, " smn" , " listen ..." );
445458
446459 s_server->listen (" 127.0.0.1" , port);
0 commit comments