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 26  
27 27 PACKAGE_NAME=@PACKAGE_NAME@
28 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 31 #---[ Paths ]------------------------------------------------------------------
32 32  
... ...
src/java/jni3270.cbp
... ... @@ -61,6 +61,7 @@
61 61 <Unit filename="main.cc" />
62 62 <Unit filename="plugin.cc" />
63 63 <Unit filename="private.h" />
  64 + <Unit filename="startstop.cc" />
64 65 <Unit filename="terminal.java" />
65 66 <Unit filename="testprogram.java" />
66 67 <Extensions>
... ...
src/java/plugin.cc
... ... @@ -325,528 +325,10 @@
325 325  
326 326 extern "C" {
327 327  
328   - static session * factory(const char *name) {
  328 + session * factory(const char *name) {
329 329 debug("---> %s",__FUNCTION__);
330 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 43  
44 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 @@
  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 +
... ...