Commit 1ab298e60634a793d0ea633c422ac2fa028fb6a6
1 parent
5555ae85
Exists in
master
and in
5 other branches
Separando star/stop da jvm da classe de plugin para facilitar
Showing
5 changed files
with
592 additions
and
521 deletions
Show diff stats
src/java/Makefile.in
@@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
26 | 26 | ||
27 | PACKAGE_NAME=@PACKAGE_NAME@ | 27 | PACKAGE_NAME=@PACKAGE_NAME@ |
28 | SOURCES=main.cc info.cc connect.cc getset.cc cursor.cc keyboard.cc actions.cc field.cc dialog.cc clipboard.cc | 28 | SOURCES=main.cc info.cc connect.cc getset.cc cursor.cc keyboard.cc actions.cc field.cc dialog.cc clipboard.cc |
29 | -PLUGIN_SRC=plugin.cc | 29 | +PLUGIN_SRC=plugin.cc startstop.cc |
30 | 30 | ||
31 | #---[ Paths ]------------------------------------------------------------------ | 31 | #---[ Paths ]------------------------------------------------------------------ |
32 | 32 |
src/java/jni3270.cbp
@@ -61,6 +61,7 @@ | @@ -61,6 +61,7 @@ | ||
61 | <Unit filename="main.cc" /> | 61 | <Unit filename="main.cc" /> |
62 | <Unit filename="plugin.cc" /> | 62 | <Unit filename="plugin.cc" /> |
63 | <Unit filename="private.h" /> | 63 | <Unit filename="private.h" /> |
64 | + <Unit filename="startstop.cc" /> | ||
64 | <Unit filename="terminal.java" /> | 65 | <Unit filename="terminal.java" /> |
65 | <Unit filename="testprogram.java" /> | 66 | <Unit filename="testprogram.java" /> |
66 | <Extensions> | 67 | <Extensions> |
src/java/plugin.cc
@@ -325,528 +325,10 @@ | @@ -325,528 +325,10 @@ | ||
325 | 325 | ||
326 | extern "C" { | 326 | extern "C" { |
327 | 327 | ||
328 | - static session * factory(const char *name) { | 328 | + session * factory(const char *name) { |
329 | debug("---> %s",__FUNCTION__); | 329 | debug("---> %s",__FUNCTION__); |
330 | return new plugin(lib3270_get_default_session_handle()); | 330 | return new plugin(lib3270_get_default_session_handle()); |
331 | } | 331 | } |
332 | 332 | ||
333 | - static void trace_cleanup(GtkWidget *widget, GtkWidget **window) { | ||
334 | - *window = NULL; | ||
335 | - } | ||
336 | - | ||
337 | - static jint JNICALL jni_vfprintf(FILE *fp, const char *fmt, va_list args) { | ||
338 | - | ||
339 | - char * msg = NULL; | ||
340 | - static GtkWidget * trace = NULL; | ||
341 | - | ||
342 | - if(vasprintf(&msg,fmt,args) < 1) { | ||
343 | - lib3270_write_log(lib3270_get_default_session_handle(),"java","vasprintf() error on \"%s\"",fmt); | ||
344 | - return 0; | ||
345 | - } | ||
346 | - | ||
347 | - fprintf(fp,"%s",msg); | ||
348 | - lib3270_write_log(lib3270_get_default_session_handle(),"java","%s",msg); | ||
349 | - | ||
350 | - if(!trace) { | ||
351 | - // Cria janela de trace. | ||
352 | - trace = pw3270_trace_new(); | ||
353 | - g_signal_connect(G_OBJECT(trace), "destroy",G_CALLBACK(trace_cleanup), &trace); | ||
354 | - | ||
355 | - pw3270_trace_set_destroy_on_close(trace,TRUE); | ||
356 | - | ||
357 | - // gtk_window_set_transient_for(GTK_WINDOW(trace),GTK_WINDOW(gtk_widget_get_toplevel(widget))); | ||
358 | - gtk_window_set_destroy_with_parent(GTK_WINDOW(trace),TRUE); | ||
359 | - | ||
360 | - gtk_window_set_default_size(GTK_WINDOW(trace),590,430); | ||
361 | - gtk_widget_show_all(trace); | ||
362 | - | ||
363 | - pw3270_trace_printf(trace,"%s",msg); | ||
364 | - | ||
365 | - free(msg); | ||
366 | - } | ||
367 | - | ||
368 | - return 0; | ||
369 | - } | ||
370 | - | ||
371 | -} | ||
372 | - | ||
373 | -#ifdef _WIN32 | ||
374 | - /* | ||
375 | - * Dynamically load jvm to avoid naming and path problems | ||
376 | - * | ||
377 | - */ | ||
378 | - static void load_jvm(GtkWidget *widget, HMODULE &hModule) { | ||
379 | - | ||
380 | - // Dynamically load jvm library to avoid naming and path problems. | ||
381 | - HMODULE kernel; | ||
382 | - HANDLE WINAPI (*AddDllDirectory)(PCWSTR NewDirectory); | ||
383 | - BOOL WINAPI (*RemoveDllDirectory)(HANDLE Cookie); | ||
384 | - | ||
385 | - struct _dlldir { | ||
386 | - const gchar * env; | ||
387 | - const gchar * path; | ||
388 | - HANDLE cookie; | ||
389 | - } dlldir[] = { | ||
390 | - { "JRE_HOME", "bin\\client", 0 }, | ||
391 | - { "JDK_HOME", "jre\\bin\\client", 0 } | ||
392 | - }; | ||
393 | - | ||
394 | - kernel = LoadLibrary("kernel32.dll"); | ||
395 | - | ||
396 | - debug("---[ %s ]---------------------------------------------------",__FUNCTION__); | ||
397 | - | ||
398 | - AddDllDirectory = (HANDLE WINAPI (*)(PCWSTR)) GetProcAddress(kernel,"AddDllDirectory"); | ||
399 | - if(AddDllDirectory) { | ||
400 | - | ||
401 | - // Acrescenta mais caminhos para achar a dll | ||
402 | - for(size_t f = 0; f < G_N_ELEMENTS(dlldir); f++) { | ||
403 | - | ||
404 | - const char *env = getenv(dlldir[f].env); | ||
405 | - | ||
406 | - debug("%s=\"%s\"",dlldir[f].env,env); | ||
407 | - | ||
408 | - if(env) { | ||
409 | - | ||
410 | - gchar *p = g_build_filename(env,dlldir[f].path,NULL); | ||
411 | - | ||
412 | - debug("Adicionando diretório \"%s\"",p); | ||
413 | - | ||
414 | - wchar_t *path = (wchar_t *) malloc(4096*sizeof(wchar_t)); | ||
415 | - mbstowcs(path, p, 4095); | ||
416 | - dlldir[f].cookie = AddDllDirectory(path); | ||
417 | - free(path); | ||
418 | - | ||
419 | - g_free(p); | ||
420 | - | ||
421 | - } | ||
422 | - } | ||
423 | - | ||
424 | - } | ||
425 | -#ifdef DEBUG | ||
426 | - else { | ||
427 | - debug("Can't get %s: %s","AddDllDirectory",session::win32_strerror(GetLastError()).c_str()) | ||
428 | - } | ||
429 | -#endif // DEBUG | ||
430 | - | ||
431 | - hModule = LoadLibrary("jvm.dll"); | ||
432 | - | ||
433 | - debug("hModule=%08lx",(long) hModule); | ||
434 | - | ||
435 | - if(!hModule) { | ||
436 | - | ||
437 | - DWORD err = GetLastError(); | ||
438 | - | ||
439 | - debug("%s",session::win32_strerror(err).c_str()); | ||
440 | - | ||
441 | - GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
442 | - GTK_DIALOG_DESTROY_WITH_PARENT, | ||
443 | - GTK_MESSAGE_ERROR, | ||
444 | - GTK_BUTTONS_CANCEL, | ||
445 | - "%s", _( "Can't load java virtual machine" ) ); | ||
446 | - | ||
447 | - gtk_window_set_title(GTK_WINDOW(dialog),_( "JVM error" )); | ||
448 | - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s", session::win32_strerror(err).c_str()); | ||
449 | - | ||
450 | - gtk_dialog_run(GTK_DIALOG (dialog)); | ||
451 | - gtk_widget_destroy(dialog); | ||
452 | - | ||
453 | - } | ||
454 | - | ||
455 | - // Libera caminhos extras. | ||
456 | - RemoveDllDirectory = (BOOL WINAPI (*)(HANDLE)) GetProcAddress(kernel,"RemoveDllDirectory"); | ||
457 | - if(RemoveDllDirectory) { | ||
458 | - | ||
459 | - for(size_t f = 0; f < G_N_ELEMENTS(dlldir); f++) { | ||
460 | - | ||
461 | - if(dlldir[f].cookie) { | ||
462 | - | ||
463 | - RemoveDllDirectory(dlldir[f].cookie); | ||
464 | - | ||
465 | - } | ||
466 | - } | ||
467 | - | ||
468 | - } | ||
469 | -#ifdef DEBUG | ||
470 | - else { | ||
471 | - debug("Can't get %s: %s","RemoveDllDirectory",session::win32_strerror(GetLastError()).c_str()) | ||
472 | - } | ||
473 | -#endif // DEBUG | ||
474 | - | ||
475 | - FreeLibrary(kernel); | ||
476 | - | ||
477 | - } | ||
478 | - | ||
479 | - | ||
480 | -#endif // _WIN32 | ||
481 | - | ||
482 | - | ||
483 | - LIB3270_EXPORT int pw3270_plugin_start(GtkWidget *window) | ||
484 | - { | ||
485 | - trace("JAVA: %s",__FUNCTION__); | ||
486 | -#if GTK_CHECK_VERSION(2,32,0) | ||
487 | - g_mutex_init(&mutex); | ||
488 | -#endif // GTK_CHECK_VERSION | ||
489 | - set_java_session_factory(factory); | ||
490 | - return 0; | ||
491 | - } | ||
492 | - | ||
493 | - LIB3270_EXPORT int pw3270_plugin_stop(GtkWidget *window) | ||
494 | - { | ||
495 | -#if GTK_CHECK_VERSION(2,32,0) | ||
496 | - g_mutex_clear(&mutex); | ||
497 | -#endif // GTK_CHECK_VERSION | ||
498 | - trace("JAVA: %s",__FUNCTION__); | ||
499 | - return 0; | ||
500 | - } | ||
501 | - | ||
502 | -extern "C" | ||
503 | -{ | ||
504 | - | ||
505 | - void call_java_program(GtkAction *action, GtkWidget *widget, const gchar *filename) | ||
506 | - { | ||
507 | - | ||
508 | -#if GTK_CHECK_VERSION(2,32,0) | ||
509 | - if(!g_mutex_trylock(&mutex)) { | ||
510 | -#else | ||
511 | - if(!g_static_mutex_trylock(&mutex)) { | ||
512 | -#endif // GTK_CHECK_VERSION | ||
513 | - | ||
514 | - GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
515 | - GTK_DIALOG_DESTROY_WITH_PARENT, | ||
516 | - GTK_MESSAGE_ERROR, | ||
517 | - GTK_BUTTONS_CANCEL, | ||
518 | - _( "Can't start %s program" ), "java" ); | ||
519 | - | ||
520 | - gtk_window_set_title(GTK_WINDOW(dialog),_( "JVM busy" )); | ||
521 | - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),_( "%s interpreter is busy" ), "java"); | ||
522 | - | ||
523 | - gtk_dialog_run(GTK_DIALOG (dialog)); | ||
524 | - gtk_widget_destroy(dialog); | ||
525 | - | ||
526 | - return; | ||
527 | - } | ||
528 | - | ||
529 | - v3270_set_script(widget,'J',TRUE); | ||
530 | - | ||
531 | -#ifdef _WIN32 | ||
532 | - | ||
533 | - HMODULE hJVM = 0; | ||
534 | - | ||
535 | - load_jvm(widget,hJVM); | ||
536 | - | ||
537 | - debug("hJVM=%p",hJVM); | ||
538 | - | ||
539 | - if(!hJVM) { | ||
540 | - v3270_set_script(widget,'J',FALSE); | ||
541 | - | ||
542 | -#if GTK_CHECK_VERSION(2,32,0) | ||
543 | - g_mutex_unlock(&mutex); | ||
544 | -#else | ||
545 | - g_static_mutex_unlock(&mutex); | ||
546 | -#endif // GTK_CHECK_VERSION | ||
547 | - | ||
548 | - return; | ||
549 | - | ||
550 | - } | ||
551 | - | ||
552 | -#endif // _WIN32 | ||
553 | - | ||
554 | - debug("%s",__FUNCTION__); | ||
555 | - | ||
556 | - // Start JNI | ||
557 | - JavaVMInitArgs vm_args; | ||
558 | - JavaVMOption options[5]; | ||
559 | - | ||
560 | - JavaVM * jvm = NULL; | ||
561 | - JNIEnv * env = NULL; | ||
562 | - jint rc = 0; | ||
563 | - | ||
564 | - memset(&vm_args,0,sizeof(vm_args)); | ||
565 | - memset(options,0,sizeof(options)); | ||
566 | - | ||
567 | - vm_args.version = JNI_VERSION_1_4; | ||
568 | - vm_args.nOptions = 0; | ||
569 | - vm_args.options = options; | ||
570 | - vm_args.ignoreUnrecognized = JNI_FALSE; | ||
571 | - | ||
572 | - options[vm_args.nOptions].optionString = g_strdup("vfprintf"); | ||
573 | - options[vm_args.nOptions].extraInfo = (void *) jni_vfprintf; | ||
574 | - vm_args.nOptions++; | ||
575 | - | ||
576 | -//#ifdef DEBUG | ||
577 | -// options[vm_args.nOptions++].optionString = g_strdup("-verbose"); | ||
578 | -//#endif | ||
579 | - | ||
580 | - gchar * dirname = g_path_get_dirname(filename); | ||
581 | - | ||
582 | - debug("Dirname=%s",dirname); | ||
583 | - | ||
584 | -#if defined( WIN32 ) | ||
585 | - | ||
586 | - gchar * exports = NULL; | ||
587 | - char buffer[1024]; | ||
588 | - gchar * myDir; | ||
589 | - | ||
590 | - if(GetModuleFileName(NULL,buffer,sizeof(buffer)) < sizeof(buffer)) { | ||
591 | - | ||
592 | - gchar * ptr = strrchr(buffer,G_DIR_SEPARATOR); | ||
593 | - if(ptr) { | ||
594 | - *ptr = 0; | ||
595 | - myDir = g_strdup(buffer); | ||
596 | - } else { | ||
597 | - myDir = g_strdup("."); | ||
598 | - } | ||
599 | - | ||
600 | - | ||
601 | - } else { | ||
602 | - | ||
603 | - myDir = g_strdup("."); | ||
604 | - | ||
605 | - } | ||
606 | - | ||
607 | - debug("myDir=%s",myDir); | ||
608 | - | ||
609 | - exports = g_build_filename(myDir,"jvm-exports",NULL); | ||
610 | - g_mkdir_with_parents(exports,0777); | ||
611 | - | ||
612 | - lib3270_trace_event(v3270_get_session(widget),"java.class.path=%s;%s",dirname,exports); | ||
613 | - lib3270_trace_event(v3270_get_session(widget),"java.library.path=%s",myDir); | ||
614 | - | ||
615 | - options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.library.path=%s",myDir); | ||
616 | - options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.class.path=%s;%s",dirname,exports); | ||
617 | - | ||
618 | - g_free(myDir); | ||
619 | - g_free(exports); | ||
620 | - | ||
621 | - // Windows, first find the method, then call it. | ||
622 | - jint JNICALL (*CreateJavaVM)(JavaVM **, void **, void *) = (jint JNICALL (*)(JavaVM **, void **, void *)) GetProcAddress(hJVM,"JNI_CreateJavaVM"); | ||
623 | - | ||
624 | - if(!CreateJavaVM) { | ||
625 | - rc = ENOENT; | ||
626 | - } else { | ||
627 | - debug("Calling %s","CreateJavaVM"); | ||
628 | - rc = CreateJavaVM(&jvm,(void **)&env,&vm_args); | ||
629 | - debug("%s exits with rc=%d","CreateJavaVM",rc); | ||
630 | - } | ||
631 | - | ||
632 | -#else | ||
633 | - | ||
634 | -#if defined(DEBUG) | ||
635 | - options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.library.path=%s:.bin/Debug:.bin/Debug/lib",JNIDIR); | ||
636 | - options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.class.path=%s:%s:./src/java/.bin/java",JARDIR,dirname); | ||
637 | -#else | ||
638 | - options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.library.path=%s",JNIDIR); | ||
639 | - options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.class.path=%s:%s",JARDIR,dirname); | ||
640 | -#endif // JNIDIR | ||
641 | - | ||
642 | - // Linux, just create JVM | ||
643 | - rc = JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args); | ||
644 | - | ||
645 | -#endif // _WIn32 | ||
646 | - | ||
647 | - debug("JNI_CreateJavaVM exits with rc=%d",rc); | ||
648 | - | ||
649 | - g_free(dirname); | ||
650 | - | ||
651 | - | ||
652 | - // Release options | ||
653 | - for(int f=0;f<vm_args.nOptions;f++) { | ||
654 | - trace("Releasing option %d: %s",f,options[f].optionString); | ||
655 | - g_free(options[f].optionString); | ||
656 | - } | ||
657 | - | ||
658 | - if(rc < 0) { | ||
659 | - | ||
660 | - GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
661 | - GTK_DIALOG_DESTROY_WITH_PARENT, | ||
662 | - GTK_MESSAGE_ERROR, | ||
663 | - GTK_BUTTONS_CANCEL, | ||
664 | - "%s", _( "Can't create java VM" )); | ||
665 | - | ||
666 | - gtk_window_set_title(GTK_WINDOW(dialog), _( "Script startup failure" )); | ||
667 | - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),_( "The error code was %d" ), (int) rc); | ||
668 | - | ||
669 | - gtk_dialog_run(GTK_DIALOG (dialog)); | ||
670 | - gtk_widget_destroy(dialog); | ||
671 | - | ||
672 | - } else { | ||
673 | - | ||
674 | - gchar * classname = g_path_get_basename(filename); | ||
675 | - | ||
676 | - gchar * ptr = strchr(classname,'.'); | ||
677 | - if(ptr) { | ||
678 | - *ptr = 0; | ||
679 | - } | ||
680 | - | ||
681 | - jclass cls = env->FindClass(classname); | ||
682 | - | ||
683 | - if(cls == 0) { | ||
684 | - | ||
685 | - GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
686 | - GTK_DIALOG_DESTROY_WITH_PARENT, | ||
687 | - GTK_MESSAGE_ERROR, | ||
688 | - GTK_BUTTONS_CANCEL, | ||
689 | - _( "Can't find class %s" ), classname ); | ||
690 | - | ||
691 | - gtk_window_set_title(GTK_WINDOW(dialog), _( "Java error" )); | ||
692 | - if(gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) | ||
693 | - gtk_main_quit(); | ||
694 | - gtk_widget_destroy(dialog); | ||
695 | - | ||
696 | - } else { | ||
697 | - | ||
698 | - jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V"); | ||
699 | - | ||
700 | - if(mid == 0) { | ||
701 | - | ||
702 | - GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
703 | - GTK_DIALOG_DESTROY_WITH_PARENT, | ||
704 | - GTK_MESSAGE_ERROR, | ||
705 | - GTK_BUTTONS_OK_CANCEL, | ||
706 | - _( "Can't find class \"%s\"" ), classname ); | ||
707 | - | ||
708 | - gtk_window_set_title(GTK_WINDOW(dialog), _( "Java error" )); | ||
709 | - | ||
710 | - if(gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) | ||
711 | - gtk_main_quit(); | ||
712 | - gtk_widget_destroy(dialog); | ||
713 | - | ||
714 | - } else { | ||
715 | - | ||
716 | - jobjectArray args = env->NewObjectArray(0, env->FindClass("java/lang/String"), env->NewStringUTF("")); | ||
717 | - | ||
718 | - try { | ||
719 | - | ||
720 | - debug("%s: Calling CallStaticVoidMethod()",__FUNCTION__); | ||
721 | - env->CallStaticVoidMethod(cls, mid, args); | ||
722 | - debug("%s: CallStaticVoidMethod() has returned",__FUNCTION__); | ||
723 | - | ||
724 | - jthrowable exc = env->ExceptionOccurred(); | ||
725 | - env->ExceptionClear(); | ||
726 | - | ||
727 | - if (exc) { | ||
728 | - jclass throwable_class = env->FindClass("java/lang/Throwable"); | ||
729 | - | ||
730 | - jmethodID jni_getMessage = env->GetMethodID(throwable_class,"getMessage","()Ljava/lang/String;"); | ||
731 | - jstring j_msg = (jstring) env->CallObjectMethod(exc,jni_getMessage); | ||
732 | - | ||
733 | - GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
734 | - GTK_DIALOG_DESTROY_WITH_PARENT, | ||
735 | - GTK_MESSAGE_ERROR, | ||
736 | - GTK_BUTTONS_OK_CANCEL, | ||
737 | - _( "Java application \"%s\" has failed." ), classname ); | ||
738 | - | ||
739 | - gtk_window_set_title(GTK_WINDOW(dialog), _( "Java failure" )); | ||
740 | - | ||
741 | - if(!env->IsSameObject(j_msg,NULL)) { | ||
742 | - | ||
743 | - const char * msg = env->GetStringUTFChars(j_msg, 0); | ||
744 | - | ||
745 | - debug("jni_getMessage = %s",msg); | ||
746 | - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s",msg); | ||
747 | - | ||
748 | - env->ReleaseStringUTFChars( j_msg, msg); | ||
749 | - } | ||
750 | - | ||
751 | - if(gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) | ||
752 | - gtk_main_quit(); | ||
753 | - gtk_widget_destroy(dialog); | ||
754 | - | ||
755 | - | ||
756 | - } | ||
757 | - | ||
758 | - } catch(std::exception &e) { | ||
759 | - | ||
760 | - debug("Java error: %s",e.what()); | ||
761 | - trace("%s",e.what()); | ||
762 | - } | ||
763 | - | ||
764 | - | ||
765 | - } | ||
766 | - | ||
767 | - } | ||
768 | - | ||
769 | - g_free(classname); | ||
770 | - | ||
771 | - jvm->DestroyJavaVM(); | ||
772 | - } | ||
773 | - | ||
774 | -#ifdef _WIN32 | ||
775 | - if(hJVM) | ||
776 | - FreeLibrary(hJVM); | ||
777 | -#endif // _WIN32 | ||
778 | - | ||
779 | - // And release | ||
780 | - v3270_set_script(widget,'J',FALSE); | ||
781 | - | ||
782 | -#if GTK_CHECK_VERSION(2,32,0) | ||
783 | - g_mutex_unlock(&mutex); | ||
784 | -#else | ||
785 | - g_static_mutex_unlock(&mutex); | ||
786 | -#endif // GTK_CHECK_VERSION | ||
787 | - | ||
788 | - | ||
789 | - } | ||
790 | - | ||
791 | - LIB3270_EXPORT void pw3270_action_java_activated(GtkAction *action, GtkWidget *widget) | ||
792 | - { | ||
793 | - gchar *filename = (gchar *) g_object_get_data(G_OBJECT(action),"src"); | ||
794 | - | ||
795 | - lib3270_trace_event(v3270_get_session(widget),"Action %s activated on widget %p",gtk_action_get_name(action),widget); | ||
796 | - | ||
797 | -#if GTK_CHECK_VERSION(3,10,0) | ||
798 | - g_simple_action_set_enabled(G_SIMPLE_ACTION(action),FALSE); | ||
799 | -#else | ||
800 | - gtk_action_set_sensitive(action,FALSE); | ||
801 | -#endif // GTK(3,10) | ||
802 | - | ||
803 | - if(filename) | ||
804 | - { | ||
805 | - // Has filename, call it directly | ||
806 | - call_java_program(action,widget,filename); | ||
807 | - } | ||
808 | - else | ||
809 | - { | ||
810 | - // No filename, ask user | ||
811 | - static const struct _list | ||
812 | - { | ||
813 | - const gchar *name; | ||
814 | - const gchar *pattern; | ||
815 | - } list[] = | ||
816 | - { | ||
817 | - { N_( "Java class file" ), "*.class" } | ||
818 | - }; | ||
819 | - | ||
820 | - GtkFileFilter * filter[G_N_ELEMENTS(list)+1]; | ||
821 | - unsigned int f; | ||
822 | - | ||
823 | - memset(filter,0,sizeof(filter)); | ||
824 | - | ||
825 | - for(f=0;f<G_N_ELEMENTS(list);f++) | ||
826 | - { | ||
827 | - filter[f] = gtk_file_filter_new(); | ||
828 | - gtk_file_filter_set_name(filter[f],gettext(list[f].name)); | ||
829 | - gtk_file_filter_add_pattern(filter[f],list[f].pattern); | ||
830 | - } | ||
831 | - | ||
832 | - filename = pw3270_get_filename(widget,"java","script",filter,_( "Select script to run" )); | ||
833 | - | ||
834 | - if(filename) | ||
835 | - { | ||
836 | - call_java_program(action,widget,filename); | ||
837 | - g_free(filename); | ||
838 | - } | ||
839 | - | ||
840 | - | ||
841 | - } | ||
842 | - | ||
843 | -#if GTK_CHECK_VERSION(3,10,0) | ||
844 | - g_simple_action_set_enabled(G_SIMPLE_ACTION(action),TRUE); | ||
845 | -#else | ||
846 | - gtk_action_set_sensitive(action,TRUE); | ||
847 | -#endif // GTK(3,10) | ||
848 | - | ||
849 | - } | ||
850 | - | ||
851 | } | 333 | } |
852 | 334 |
src/java/private.h
@@ -43,7 +43,8 @@ | @@ -43,7 +43,8 @@ | ||
43 | 43 | ||
44 | extern "C" { | 44 | extern "C" { |
45 | 45 | ||
46 | - LIB3270_EXPORT void set_java_session_factory(PW3270_NAMESPACE::session * (*factory)(const char *name)); | 46 | + LIB3270_EXPORT void set_java_session_factory(PW3270_NAMESPACE::session * (*factory)(const char *name)); |
47 | + extern session * factory(const char *name); | ||
47 | 48 | ||
48 | } | 49 | } |
49 | 50 |
@@ -0,0 +1,587 @@ | @@ -0,0 +1,587 @@ | ||
1 | +/* | ||
2 | + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 | ||
3 | + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a | ||
4 | + * aplicativos mainframe. Registro no INPI sob o nome G3270. | ||
5 | + * | ||
6 | + * Copyright (C) <2008> <Banco do Brasil S.A.> | ||
7 | + * | ||
8 | + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob | ||
9 | + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela | ||
10 | + * Free Software Foundation. | ||
11 | + * | ||
12 | + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER | ||
13 | + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO | ||
14 | + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para | ||
15 | + * obter mais detalhes. | ||
16 | + * | ||
17 | + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este | ||
18 | + * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple | ||
19 | + * Place, Suite 330, Boston, MA, 02111-1307, USA | ||
20 | + * | ||
21 | + * Este programa está nomeado como startstop.cc e possui - linhas de código. | ||
22 | + * | ||
23 | + * Contatos: | ||
24 | + * | ||
25 | + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) | ||
26 | + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) | ||
27 | + * | ||
28 | + */ | ||
29 | + | ||
30 | +#if defined WIN32 | ||
31 | + | ||
32 | + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx | ||
33 | + #ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | ||
34 | + #define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000 | ||
35 | + #endif // LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | ||
36 | + | ||
37 | + #ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | ||
38 | + #define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100 | ||
39 | + #endif // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | ||
40 | + | ||
41 | + #include <windows.h> | ||
42 | + | ||
43 | +#else | ||
44 | + | ||
45 | + #include <dlfcn.h> | ||
46 | + | ||
47 | +#endif | ||
48 | + | ||
49 | + #include "private.h" | ||
50 | + | ||
51 | + #include <malloc.h> | ||
52 | + #include <libintl.h> | ||
53 | + #include <glib/gi18n.h> | ||
54 | + #include <gtk/gtk.h> | ||
55 | + | ||
56 | + #include <pw3270.h> | ||
57 | + #include <pw3270/plugin.h> | ||
58 | + #include <pw3270/v3270.h> | ||
59 | + #include <lib3270/actions.h> | ||
60 | + #include <lib3270/log.h> | ||
61 | + #include <lib3270/trace.h> | ||
62 | + #include <lib3270/charset.h> | ||
63 | + #include <pw3270/class.h> | ||
64 | + #include <pw3270/trace.h> | ||
65 | + | ||
66 | +/*--[ Globals ]--------------------------------------------------------------------------------------*/ | ||
67 | + | ||
68 | +#if GTK_CHECK_VERSION(2,32,0) | ||
69 | + static GMutex mutex; | ||
70 | + | ||
71 | + #define trylock() g_mutex_trylock(&mutex) | ||
72 | + #define lock() g_mutex_lock(&mutex) | ||
73 | + #define unlock() g_mutex_unlock(&mutex) | ||
74 | + | ||
75 | +#else | ||
76 | + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; | ||
77 | + | ||
78 | + #define trylock() g_static_mutex_trylock(&mutex) | ||
79 | + #define lock() g_static_mutex_lock(&mutex) | ||
80 | + #define unlock() g_static_mutex_unlock(&mutex) | ||
81 | + | ||
82 | +#endif // GTK_CHECK_VERSION | ||
83 | + | ||
84 | +/*---[ Implement ]----------------------------------------------------------------------------------*/ | ||
85 | + | ||
86 | +extern "C" { | ||
87 | + | ||
88 | + static void trace_cleanup(GtkWidget *widget, GtkWidget **window) { | ||
89 | + *window = NULL; | ||
90 | + } | ||
91 | + | ||
92 | + static jint JNICALL jni_vfprintf(FILE *fp, const char *fmt, va_list args) { | ||
93 | + | ||
94 | + char * msg = NULL; | ||
95 | + static GtkWidget * trace = NULL; | ||
96 | + | ||
97 | + if(vasprintf(&msg,fmt,args) < 1) { | ||
98 | + lib3270_write_log(lib3270_get_default_session_handle(),"java","vasprintf() error on \"%s\"",fmt); | ||
99 | + return 0; | ||
100 | + } | ||
101 | + | ||
102 | + fprintf(fp,"%s",msg); | ||
103 | + lib3270_write_log(lib3270_get_default_session_handle(),"java","%s",msg); | ||
104 | + | ||
105 | + if(!trace) { | ||
106 | + // Cria janela de trace. | ||
107 | + trace = pw3270_trace_new(); | ||
108 | + g_signal_connect(G_OBJECT(trace), "destroy",G_CALLBACK(trace_cleanup), &trace); | ||
109 | + | ||
110 | + pw3270_trace_set_destroy_on_close(trace,TRUE); | ||
111 | + | ||
112 | + // gtk_window_set_transient_for(GTK_WINDOW(trace),GTK_WINDOW(gtk_widget_get_toplevel(widget))); | ||
113 | + gtk_window_set_destroy_with_parent(GTK_WINDOW(trace),TRUE); | ||
114 | + | ||
115 | + gtk_window_set_default_size(GTK_WINDOW(trace),590,430); | ||
116 | + gtk_widget_show_all(trace); | ||
117 | + | ||
118 | + pw3270_trace_printf(trace,"%s",msg); | ||
119 | + | ||
120 | + free(msg); | ||
121 | + } | ||
122 | + | ||
123 | + return 0; | ||
124 | + } | ||
125 | + | ||
126 | +} | ||
127 | + | ||
128 | +#ifdef _WIN32 | ||
129 | + /* | ||
130 | + * Dynamically load jvm to avoid naming and path problems | ||
131 | + * | ||
132 | + */ | ||
133 | + static void load_jvm(GtkWidget *widget, HMODULE &hModule) { | ||
134 | + | ||
135 | + // Dynamically load jvm library to avoid naming and path problems. | ||
136 | + HMODULE kernel; | ||
137 | + HANDLE WINAPI (*AddDllDirectory)(PCWSTR NewDirectory); | ||
138 | + BOOL WINAPI (*RemoveDllDirectory)(HANDLE Cookie); | ||
139 | + | ||
140 | + struct _dlldir { | ||
141 | + const gchar * env; | ||
142 | + const gchar * path; | ||
143 | + HANDLE cookie; | ||
144 | + } dlldir[] = { | ||
145 | + { "JRE_HOME", "bin\\client", 0 }, | ||
146 | + { "JDK_HOME", "jre\\bin\\client", 0 } | ||
147 | + }; | ||
148 | + | ||
149 | + kernel = LoadLibrary("kernel32.dll"); | ||
150 | + | ||
151 | + debug("---[ %s ]---------------------------------------------------",__FUNCTION__); | ||
152 | + | ||
153 | + AddDllDirectory = (HANDLE WINAPI (*)(PCWSTR)) GetProcAddress(kernel,"AddDllDirectory"); | ||
154 | + if(AddDllDirectory) { | ||
155 | + | ||
156 | + // Acrescenta mais caminhos para achar a dll | ||
157 | + for(size_t f = 0; f < G_N_ELEMENTS(dlldir); f++) { | ||
158 | + | ||
159 | + const char *env = getenv(dlldir[f].env); | ||
160 | + | ||
161 | + debug("%s=\"%s\"",dlldir[f].env,env); | ||
162 | + | ||
163 | + if(env) { | ||
164 | + | ||
165 | + gchar *p = g_build_filename(env,dlldir[f].path,NULL); | ||
166 | + | ||
167 | + debug("Adicionando diretório \"%s\"",p); | ||
168 | + | ||
169 | + wchar_t *path = (wchar_t *) malloc(4096*sizeof(wchar_t)); | ||
170 | + mbstowcs(path, p, 4095); | ||
171 | + dlldir[f].cookie = AddDllDirectory(path); | ||
172 | + free(path); | ||
173 | + | ||
174 | + g_free(p); | ||
175 | + | ||
176 | + } | ||
177 | + } | ||
178 | + | ||
179 | + } | ||
180 | +#ifdef DEBUG | ||
181 | + else { | ||
182 | + debug("Can't get %s: %s","AddDllDirectory",session::win32_strerror(GetLastError()).c_str()) | ||
183 | + } | ||
184 | +#endif // DEBUG | ||
185 | + | ||
186 | + hModule = LoadLibrary("jvm.dll"); | ||
187 | + | ||
188 | + debug("hModule=%08lx",(long) hModule); | ||
189 | + | ||
190 | + if(!hModule) { | ||
191 | + | ||
192 | + DWORD err = GetLastError(); | ||
193 | + | ||
194 | + debug("%s",session::win32_strerror(err).c_str()); | ||
195 | + | ||
196 | + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
197 | + GTK_DIALOG_DESTROY_WITH_PARENT, | ||
198 | + GTK_MESSAGE_ERROR, | ||
199 | + GTK_BUTTONS_CANCEL, | ||
200 | + "%s", _( "Can't load java virtual machine" ) ); | ||
201 | + | ||
202 | + gtk_window_set_title(GTK_WINDOW(dialog),_( "JVM error" )); | ||
203 | + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s", session::win32_strerror(err).c_str()); | ||
204 | + | ||
205 | + gtk_dialog_run(GTK_DIALOG (dialog)); | ||
206 | + gtk_widget_destroy(dialog); | ||
207 | + | ||
208 | + } | ||
209 | + | ||
210 | + // Libera caminhos extras. | ||
211 | + RemoveDllDirectory = (BOOL WINAPI (*)(HANDLE)) GetProcAddress(kernel,"RemoveDllDirectory"); | ||
212 | + if(RemoveDllDirectory) { | ||
213 | + | ||
214 | + for(size_t f = 0; f < G_N_ELEMENTS(dlldir); f++) { | ||
215 | + | ||
216 | + if(dlldir[f].cookie) { | ||
217 | + | ||
218 | + RemoveDllDirectory(dlldir[f].cookie); | ||
219 | + | ||
220 | + } | ||
221 | + } | ||
222 | + | ||
223 | + } | ||
224 | +#ifdef DEBUG | ||
225 | + else { | ||
226 | + debug("Can't get %s: %s","RemoveDllDirectory",session::win32_strerror(GetLastError()).c_str()) | ||
227 | + } | ||
228 | +#endif // DEBUG | ||
229 | + | ||
230 | + FreeLibrary(kernel); | ||
231 | + | ||
232 | + } | ||
233 | + | ||
234 | + | ||
235 | +#endif // _WIN32 | ||
236 | + | ||
237 | + | ||
238 | + LIB3270_EXPORT int pw3270_plugin_start(GtkWidget *window) | ||
239 | + { | ||
240 | + trace("JAVA: %s",__FUNCTION__); | ||
241 | +#if GTK_CHECK_VERSION(2,32,0) | ||
242 | + g_mutex_init(&mutex); | ||
243 | +#endif // GTK_CHECK_VERSION | ||
244 | + set_java_session_factory(factory); | ||
245 | + return 0; | ||
246 | + } | ||
247 | + | ||
248 | + LIB3270_EXPORT int pw3270_plugin_stop(GtkWidget *window) | ||
249 | + { | ||
250 | +#if GTK_CHECK_VERSION(2,32,0) | ||
251 | + g_mutex_clear(&mutex); | ||
252 | +#endif // GTK_CHECK_VERSION | ||
253 | + trace("JAVA: %s",__FUNCTION__); | ||
254 | + return 0; | ||
255 | + } | ||
256 | + | ||
257 | +extern "C" | ||
258 | +{ | ||
259 | + | ||
260 | + void call_java_program(GtkAction *action, GtkWidget *widget, const gchar *filename) | ||
261 | + { | ||
262 | + | ||
263 | + if(!trylock()) { | ||
264 | + | ||
265 | + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
266 | + GTK_DIALOG_DESTROY_WITH_PARENT, | ||
267 | + GTK_MESSAGE_ERROR, | ||
268 | + GTK_BUTTONS_CANCEL, | ||
269 | + _( "Can't start %s program" ), "java" ); | ||
270 | + | ||
271 | + gtk_window_set_title(GTK_WINDOW(dialog),_( "JVM busy" )); | ||
272 | + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),_( "%s interpreter is busy" ), "java"); | ||
273 | + | ||
274 | + gtk_dialog_run(GTK_DIALOG (dialog)); | ||
275 | + gtk_widget_destroy(dialog); | ||
276 | + | ||
277 | + return; | ||
278 | + } | ||
279 | + | ||
280 | + v3270_set_script(widget,'J',TRUE); | ||
281 | + | ||
282 | +#ifdef _WIN32 | ||
283 | + | ||
284 | + HMODULE hJVM = 0; | ||
285 | + | ||
286 | + load_jvm(widget,hJVM); | ||
287 | + | ||
288 | + debug("hJVM=%p",hJVM); | ||
289 | + | ||
290 | + if(!hJVM) { | ||
291 | + v3270_set_script(widget,'J',FALSE); | ||
292 | + | ||
293 | +#if GTK_CHECK_VERSION(2,32,0) | ||
294 | + g_mutex_unlock(&mutex); | ||
295 | +#else | ||
296 | + g_static_mutex_unlock(&mutex); | ||
297 | +#endif // GTK_CHECK_VERSION | ||
298 | + | ||
299 | + return; | ||
300 | + | ||
301 | + } | ||
302 | + | ||
303 | +#endif // _WIN32 | ||
304 | + | ||
305 | + debug("%s",__FUNCTION__); | ||
306 | + | ||
307 | + // Start JNI | ||
308 | + JavaVMInitArgs vm_args; | ||
309 | + JavaVMOption options[5]; | ||
310 | + | ||
311 | + JavaVM * jvm = NULL; | ||
312 | + JNIEnv * env = NULL; | ||
313 | + jint rc = 0; | ||
314 | + | ||
315 | + memset(&vm_args,0,sizeof(vm_args)); | ||
316 | + memset(options,0,sizeof(options)); | ||
317 | + | ||
318 | + vm_args.version = JNI_VERSION_1_4; | ||
319 | + vm_args.nOptions = 0; | ||
320 | + vm_args.options = options; | ||
321 | + vm_args.ignoreUnrecognized = JNI_FALSE; | ||
322 | + | ||
323 | + options[vm_args.nOptions].optionString = g_strdup("vfprintf"); | ||
324 | + options[vm_args.nOptions].extraInfo = (void *) jni_vfprintf; | ||
325 | + vm_args.nOptions++; | ||
326 | + | ||
327 | +//#ifdef DEBUG | ||
328 | +// options[vm_args.nOptions++].optionString = g_strdup("-verbose"); | ||
329 | +//#endif | ||
330 | + | ||
331 | + gchar * dirname = g_path_get_dirname(filename); | ||
332 | + | ||
333 | + debug("Dirname=%s",dirname); | ||
334 | + | ||
335 | +#if defined( WIN32 ) | ||
336 | + | ||
337 | + gchar * exports = NULL; | ||
338 | + char buffer[1024]; | ||
339 | + gchar * myDir; | ||
340 | + | ||
341 | + if(GetModuleFileName(NULL,buffer,sizeof(buffer)) < sizeof(buffer)) { | ||
342 | + | ||
343 | + gchar * ptr = strrchr(buffer,G_DIR_SEPARATOR); | ||
344 | + if(ptr) { | ||
345 | + *ptr = 0; | ||
346 | + myDir = g_strdup(buffer); | ||
347 | + } else { | ||
348 | + myDir = g_strdup("."); | ||
349 | + } | ||
350 | + | ||
351 | + | ||
352 | + } else { | ||
353 | + | ||
354 | + myDir = g_strdup("."); | ||
355 | + | ||
356 | + } | ||
357 | + | ||
358 | + debug("myDir=%s",myDir); | ||
359 | + | ||
360 | + exports = g_build_filename(myDir,"jvm-exports",NULL); | ||
361 | + g_mkdir_with_parents(exports,0777); | ||
362 | + | ||
363 | + lib3270_trace_event(v3270_get_session(widget),"java.class.path=%s;%s",dirname,exports); | ||
364 | + lib3270_trace_event(v3270_get_session(widget),"java.library.path=%s",myDir); | ||
365 | + | ||
366 | + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.library.path=%s",myDir); | ||
367 | + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.class.path=%s;%s",dirname,exports); | ||
368 | + | ||
369 | + g_free(myDir); | ||
370 | + g_free(exports); | ||
371 | + | ||
372 | + // Windows, first find the method, then call it. | ||
373 | + jint JNICALL (*CreateJavaVM)(JavaVM **, void **, void *) = (jint JNICALL (*)(JavaVM **, void **, void *)) GetProcAddress(hJVM,"JNI_CreateJavaVM"); | ||
374 | + | ||
375 | + if(!CreateJavaVM) { | ||
376 | + rc = ENOENT; | ||
377 | + } else { | ||
378 | + debug("Calling %s","CreateJavaVM"); | ||
379 | + rc = CreateJavaVM(&jvm,(void **)&env,&vm_args); | ||
380 | + debug("%s exits with rc=%d","CreateJavaVM",rc); | ||
381 | + } | ||
382 | + | ||
383 | +#else | ||
384 | + | ||
385 | +#if defined(DEBUG) | ||
386 | + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.library.path=%s:.bin/Debug:.bin/Debug/lib",JNIDIR); | ||
387 | + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.class.path=%s:%s:./src/java/.bin/java",JARDIR,dirname); | ||
388 | +#else | ||
389 | + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.library.path=%s",JNIDIR); | ||
390 | + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.class.path=%s:%s",JARDIR,dirname); | ||
391 | +#endif // JNIDIR | ||
392 | + | ||
393 | + // Linux, just create JVM | ||
394 | + rc = JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args); | ||
395 | + | ||
396 | +#endif // _WIn32 | ||
397 | + | ||
398 | + debug("JNI_CreateJavaVM exits with rc=%d",rc); | ||
399 | + | ||
400 | + g_free(dirname); | ||
401 | + | ||
402 | + | ||
403 | + // Release options | ||
404 | + for(int f=0;f<vm_args.nOptions;f++) { | ||
405 | + trace("Releasing option %d: %s",f,options[f].optionString); | ||
406 | + g_free(options[f].optionString); | ||
407 | + } | ||
408 | + | ||
409 | + if(rc < 0) { | ||
410 | + | ||
411 | + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
412 | + GTK_DIALOG_DESTROY_WITH_PARENT, | ||
413 | + GTK_MESSAGE_ERROR, | ||
414 | + GTK_BUTTONS_CANCEL, | ||
415 | + "%s", _( "Can't create java VM" )); | ||
416 | + | ||
417 | + gtk_window_set_title(GTK_WINDOW(dialog), _( "Script startup failure" )); | ||
418 | + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),_( "The error code was %d" ), (int) rc); | ||
419 | + | ||
420 | + gtk_dialog_run(GTK_DIALOG (dialog)); | ||
421 | + gtk_widget_destroy(dialog); | ||
422 | + | ||
423 | + } else { | ||
424 | + | ||
425 | + gchar * classname = g_path_get_basename(filename); | ||
426 | + | ||
427 | + gchar * ptr = strchr(classname,'.'); | ||
428 | + if(ptr) { | ||
429 | + *ptr = 0; | ||
430 | + } | ||
431 | + | ||
432 | + jclass cls = env->FindClass(classname); | ||
433 | + | ||
434 | + if(cls == 0) { | ||
435 | + | ||
436 | + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
437 | + GTK_DIALOG_DESTROY_WITH_PARENT, | ||
438 | + GTK_MESSAGE_ERROR, | ||
439 | + GTK_BUTTONS_CANCEL, | ||
440 | + _( "Can't find class %s" ), classname ); | ||
441 | + | ||
442 | + gtk_window_set_title(GTK_WINDOW(dialog), _( "Java error" )); | ||
443 | + if(gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) | ||
444 | + gtk_main_quit(); | ||
445 | + gtk_widget_destroy(dialog); | ||
446 | + | ||
447 | + } else { | ||
448 | + | ||
449 | + jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V"); | ||
450 | + | ||
451 | + if(mid == 0) { | ||
452 | + | ||
453 | + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
454 | + GTK_DIALOG_DESTROY_WITH_PARENT, | ||
455 | + GTK_MESSAGE_ERROR, | ||
456 | + GTK_BUTTONS_OK_CANCEL, | ||
457 | + _( "Can't find class \"%s\"" ), classname ); | ||
458 | + | ||
459 | + gtk_window_set_title(GTK_WINDOW(dialog), _( "Java error" )); | ||
460 | + | ||
461 | + if(gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) | ||
462 | + gtk_main_quit(); | ||
463 | + gtk_widget_destroy(dialog); | ||
464 | + | ||
465 | + } else { | ||
466 | + | ||
467 | + jobjectArray args = env->NewObjectArray(0, env->FindClass("java/lang/String"), env->NewStringUTF("")); | ||
468 | + | ||
469 | + try { | ||
470 | + | ||
471 | + debug("%s: Calling CallStaticVoidMethod()",__FUNCTION__); | ||
472 | + env->CallStaticVoidMethod(cls, mid, args); | ||
473 | + debug("%s: CallStaticVoidMethod() has returned",__FUNCTION__); | ||
474 | + | ||
475 | + jthrowable exc = env->ExceptionOccurred(); | ||
476 | + env->ExceptionClear(); | ||
477 | + | ||
478 | + if (exc) { | ||
479 | + jclass throwable_class = env->FindClass("java/lang/Throwable"); | ||
480 | + | ||
481 | + jmethodID jni_getMessage = env->GetMethodID(throwable_class,"getMessage","()Ljava/lang/String;"); | ||
482 | + jstring j_msg = (jstring) env->CallObjectMethod(exc,jni_getMessage); | ||
483 | + | ||
484 | + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW(gtk_widget_get_toplevel(widget)), | ||
485 | + GTK_DIALOG_DESTROY_WITH_PARENT, | ||
486 | + GTK_MESSAGE_ERROR, | ||
487 | + GTK_BUTTONS_OK_CANCEL, | ||
488 | + _( "Java application \"%s\" has failed." ), classname ); | ||
489 | + | ||
490 | + gtk_window_set_title(GTK_WINDOW(dialog), _( "Java failure" )); | ||
491 | + | ||
492 | + if(!env->IsSameObject(j_msg,NULL)) { | ||
493 | + | ||
494 | + const char * msg = env->GetStringUTFChars(j_msg, 0); | ||
495 | + | ||
496 | + debug("jni_getMessage = %s",msg); | ||
497 | + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s",msg); | ||
498 | + | ||
499 | + env->ReleaseStringUTFChars( j_msg, msg); | ||
500 | + } | ||
501 | + | ||
502 | + if(gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) | ||
503 | + gtk_main_quit(); | ||
504 | + gtk_widget_destroy(dialog); | ||
505 | + | ||
506 | + | ||
507 | + } | ||
508 | + | ||
509 | + } catch(std::exception &e) { | ||
510 | + | ||
511 | + debug("Java error: %s",e.what()); | ||
512 | + trace("%s",e.what()); | ||
513 | + } | ||
514 | + | ||
515 | + | ||
516 | + } | ||
517 | + | ||
518 | + } | ||
519 | + | ||
520 | + g_free(classname); | ||
521 | + | ||
522 | + rc = jvm->DestroyJavaVM(); | ||
523 | + debug("DestroyJavaVM=%d",(int) rc); | ||
524 | + } | ||
525 | + | ||
526 | +#ifdef _WIN32 | ||
527 | + if(hJVM) | ||
528 | + FreeLibrary(hJVM); | ||
529 | +#endif // _WIN32 | ||
530 | + | ||
531 | + // And release | ||
532 | + v3270_set_script(widget,'J',FALSE); | ||
533 | + | ||
534 | + unlock(); | ||
535 | + | ||
536 | + } | ||
537 | + | ||
538 | + LIB3270_EXPORT void pw3270_action_java_activated(GtkAction *action, GtkWidget *widget) | ||
539 | + { | ||
540 | + gchar *filename = (gchar *) g_object_get_data(G_OBJECT(action),"src"); | ||
541 | + | ||
542 | + lib3270_trace_event(v3270_get_session(widget),"Action %s activated on widget %p",gtk_action_get_name(action),widget); | ||
543 | + | ||
544 | + if(filename) | ||
545 | + { | ||
546 | + // Has filename, call it directly | ||
547 | + call_java_program(action,widget,filename); | ||
548 | + } | ||
549 | + else | ||
550 | + { | ||
551 | + // No filename, ask user | ||
552 | + static const struct _list | ||
553 | + { | ||
554 | + const gchar *name; | ||
555 | + const gchar *pattern; | ||
556 | + } list[] = | ||
557 | + { | ||
558 | + { N_( "Java class file" ), "*.class" } | ||
559 | + }; | ||
560 | + | ||
561 | + GtkFileFilter * filter[G_N_ELEMENTS(list)+1]; | ||
562 | + unsigned int f; | ||
563 | + | ||
564 | + memset(filter,0,sizeof(filter)); | ||
565 | + | ||
566 | + for(f=0;f<G_N_ELEMENTS(list);f++) | ||
567 | + { | ||
568 | + filter[f] = gtk_file_filter_new(); | ||
569 | + gtk_file_filter_set_name(filter[f],gettext(list[f].name)); | ||
570 | + gtk_file_filter_add_pattern(filter[f],list[f].pattern); | ||
571 | + } | ||
572 | + | ||
573 | + filename = pw3270_get_filename(widget,"java","script",filter,_( "Select script to run" )); | ||
574 | + | ||
575 | + if(filename) | ||
576 | + { | ||
577 | + call_java_program(action,widget,filename); | ||
578 | + g_free(filename); | ||
579 | + } | ||
580 | + | ||
581 | + | ||
582 | + } | ||
583 | + | ||
584 | + } | ||
585 | + | ||
586 | +} | ||
587 | + |