From 6d7b28522c0a4e1b02152f4689e41e1314acf3db Mon Sep 17 00:00:00 2001 From: perry.werneck@gmail.com Date: Sat, 4 Jul 2015 12:37:30 +0000 Subject: [PATCH] Implementando plugin e extensão java para windows --- src/java/Makefile.in | 6 +++--- src/java/private.h | 4 ++++ src/java/startstop.cc | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 165 insertions(+), 6 deletions(-) diff --git a/src/java/Makefile.in b/src/java/Makefile.in index 9b3ad1f..3a276c4 100644 --- a/src/java/Makefile.in +++ b/src/java/Makefile.in @@ -86,7 +86,7 @@ PW3270_CFLAGS ?= -I../include PLUGIN_CFLAGS=@CXXFLAGS@ -DPW3270_PLUGIN -Wno-deprecated-declarations @DLL_CFLAGS@ @JNI_CPPFLAGS@ -DJNIDIR="\"$(jnidir)\"" \ -DJARDIR="\"$(jvmjardir)\"" @GTK_CFLAGS@ @GTKMAC_CFLAGS@ $(PW3270_CFLAGS) -PLUGIN_LIBS=@GTK_LIBS@ @GTKMAC_LIBS@ @JVM_LIBS@ +PLUGIN_LIBS=@GTK_LIBS@ @GTKMAC_LIBS@ @INTL_LIBS@ @JVM_LIBS@ #---[ Rules ]------------------------------------------------------------------ @@ -190,7 +190,7 @@ $(BINRLS)@DLLDIR@/@DLLPREFIX@jni3270@DLLEXT@: \ @echo " LD `basename $@`" @$(MKDIR) `dirname $@` - @$(CXX) @SYSDLL_FLAGS@ $(LDFLAGS) -Wl,-soname,`basename $@` -o $@ $^ $(CLASS_LIBS) + @$(CXX) @SYSDLL_FLAGS@ $(LDFLAGS) -Wl,-soname,`basename $@` -o $@ $^ $(CLASS_LIBS) @INTL_LIBS@ $(BINRLS)/plugins/j3270@DLLEXT@: \ $(foreach SRC, $(basename $(PLUGIN_SRC)), $(OBJRLS)/j3270/$(SRC)@OBJEXT@) \ @@ -218,7 +218,7 @@ $(BINDBG)@DLLDIR@/@DLLPREFIX@jni3270@DLLEXT@: \ @echo " LD `basename $@`" @$(MKDIR) `dirname $@` - @$(CXX) @SYSDLL_FLAGS@ $(LDFLAGS) -Wl,-soname,`basename $@` -o $@ $^ $(CLASS_LIBS) + @$(CXX) @SYSDLL_FLAGS@ $(LDFLAGS) -Wl,-soname,`basename $@` -o $@ $^ $(CLASS_LIBS) @INTL_LIBS@ $(BINDBG)/plugins/j3270@DLLEXT@: \ $(BINDBG)@DLLDIR@/@DLLPREFIX@jni3270@DLLEXT@ \ diff --git a/src/java/private.h b/src/java/private.h index ff9c319..a7e04e5 100644 --- a/src/java/private.h +++ b/src/java/private.h @@ -49,6 +49,10 @@ namespace java { +#ifdef _WIN32 + extern HMODULE hModule; +#endif // WIN32 + extern JavaVM * jvm; extern JNIEnv * env; diff --git a/src/java/startstop.cc b/src/java/startstop.cc index 7a54bea..ff4cb94 100644 --- a/src/java/startstop.cc +++ b/src/java/startstop.cc @@ -154,8 +154,11 @@ extern "C" { namespace PW3270_NAMESPACE { - JavaVM * java::jvm = NULL; - JNIEnv * java::env = NULL; + JavaVM * java::jvm = NULL; + JNIEnv * java::env = NULL; +#ifdef _WIN32 + HMODULE java::hModule = NULL; +#endif // _WIN32 void java::failed(GtkWidget *widget, const char *msg, const char *format, ...) { @@ -189,7 +192,159 @@ extern "C" { bool java::load_jvm(GtkWidget *widget) { - #error Implementar + if(jvm != NULL) { + return true; + } + + // Dynamically load jvm library to avoid naming and path problems. + HMODULE kernel; + HANDLE WINAPI (*AddDllDirectory)(PCWSTR NewDirectory); + BOOL WINAPI (*RemoveDllDirectory)(HANDLE Cookie); + + struct _dlldir { + const gchar * env; + const gchar * path; + HANDLE cookie; + } dlldir[] = { + { "JRE_HOME", "bin\\client", 0 }, + { "JDK_HOME", "jre\\bin\\client", 0 } + }; + + kernel = LoadLibrary("kernel32.dll"); + + AddDllDirectory = (HANDLE WINAPI (*)(PCWSTR)) GetProcAddress(kernel,"AddDllDirectory"); + if(AddDllDirectory) { + + // Acrescenta mais caminhos para achar a dll + for(size_t f = 0; f < G_N_ELEMENTS(dlldir); f++) { + + const char *env = getenv(dlldir[f].env); + + debug("%s=\"%s\"",dlldir[f].env,env); + + if(env) { + + gchar *p = g_build_filename(env,dlldir[f].path,NULL); + + debug("Adicionando diretório \"%s\"",p); + + wchar_t *path = (wchar_t *) malloc(4096*sizeof(wchar_t)); + mbstowcs(path, p, 4095); + dlldir[f].cookie = AddDllDirectory(path); + free(path); + + g_free(p); + + } + } + + } + #ifdef DEBUG + else { + debug("Can't get %s: %s","AddDllDirectory",session::win32_strerror(GetLastError()).c_str()) + } + #endif // DEBUG + + hModule = LoadLibrary("jvm.dll"); + + if(hModule) { + failed(widget, _( "Can't load java virtual machine" ), "%s", session::win32_strerror(GetLastError()).c_str()); + } + + RemoveDllDirectory = (BOOL WINAPI (*)(HANDLE)) GetProcAddress(kernel,"RemoveDllDirectory"); + if(RemoveDllDirectory) { + + for(size_t f = 0; f < G_N_ELEMENTS(dlldir); f++) { + + if(dlldir[f].cookie) { + + RemoveDllDirectory(dlldir[f].cookie); + + } + } + + } + + FreeLibrary(kernel); + + if(!hModule) { + return false; + } + + // Consegui carregar a JVM, obtenho o método de controle + jint JNICALL (*CreateJavaVM)(JavaVM **, void **, void *) = (jint JNICALL (*)(JavaVM **, void **, void *)) GetProcAddress(hModule,"JNI_CreateJavaVM"); + + if(!CreateJavaVM) { + failed(widget, _( "Can't load java virtual machine creation method" ), "%s", session::win32_strerror(GetLastError()).c_str()); + return false; + } + + // Crio a JVM + JavaVMInitArgs vm_args; + JavaVMOption options[5]; + + jint rc = 0; + + memset(&vm_args,0,sizeof(vm_args)); + memset(options,0,sizeof(options)); + + vm_args.version = JNI_VERSION_1_4; + vm_args.nOptions = 0; + vm_args.options = options; + vm_args.ignoreUnrecognized = JNI_FALSE; + + options[vm_args.nOptions].optionString = g_strdup("vfprintf"); + options[vm_args.nOptions].extraInfo = (void *) jni_vfprintf; + vm_args.nOptions++; + + gchar * exports = NULL; + char buffer[1024]; + gchar * myDir; + + if(GetModuleFileName(NULL,buffer,sizeof(buffer)) < sizeof(buffer)) { + + gchar * ptr = strrchr(buffer,G_DIR_SEPARATOR); + if(ptr) { + *ptr = 0; + myDir = g_strdup(buffer); + } else { + myDir = g_strdup("."); + } + + + } else { + + myDir = g_strdup("."); + + } + + debug("myDir=%s",myDir); + + exports = g_build_filename(myDir,"jvm-exports",NULL); + g_mkdir_with_parents(exports,0777); + + lib3270_trace_event(v3270_get_session(widget),"java.class.path=%s",exports); + lib3270_trace_event(v3270_get_session(widget),"java.library.path=%s",myDir); + + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.class.path=%s",exports); + options[vm_args.nOptions++].optionString = g_strdup_printf("-Djava.library.path=%s",myDir); + + g_free(myDir); + g_free(exports); + + rc = CreateJavaVM(&jvm,(void **)&env,&vm_args); + if(rc < 0) { + failed(widget, _( "Can't create java VM" ), _( "The error code was %d" ), (int) rc); + jvm = NULL; + } + + for(int f=0;f