Commit 1ab298e60634a793d0ea633c422ac2fa028fb6a6

Authored by perry.werneck@gmail.com
1 parent 5555ae85

Separando star/stop da jvm da classe de plugin para facilitar

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
src/java/startstop.cc 0 → 100644
@@ -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 +