mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 10:56:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			617 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			617 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /************ Javaconn C++ Functions Source Code File (.CPP) ***********/
 | |
| /*  Name: JAVAConn.CPP  Version 1.1                                    */
 | |
| /*                                                                     */
 | |
| /*  (C) Copyright to the author Olivier BERTRAND          2017 - 2021  */
 | |
| /*                                                                     */
 | |
| /*  This file contains the JAVA connection classes functions.          */
 | |
| /***********************************************************************/
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| // This is needed for RegGetValue
 | |
| #define _WINVER 0x0601
 | |
| #undef  _WIN32_WINNT
 | |
| #define _WIN32_WINNT 0x0601
 | |
| #endif   // _WIN32
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Include relevant MariaDB header file.                              */
 | |
| /***********************************************************************/
 | |
| #include <my_global.h>
 | |
| //#include <m_string.h>
 | |
| #if defined(_WIN32)
 | |
| #include <direct.h>                      // for getcwd
 | |
| #if defined(__BORLANDC__)
 | |
| #define __MFC_COMPAT__                   // To define min/max as macro
 | |
| #endif   // __BORLANDC__
 | |
| #else   // !_WIN32
 | |
| #if defined(UNIX)
 | |
| #include <errno.h>
 | |
| #else   // !UNIX
 | |
| #endif  // !UNIX
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>                      // for getenv
 | |
| #define NODW
 | |
| #endif  // !_WIN32
 | |
| 
 | |
| #include <m_string.h>
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Required objects includes.                                         */
 | |
| /***********************************************************************/
 | |
| #include "global.h"
 | |
| #include "plgdbsem.h"
 | |
| #include "colblk.h"
 | |
| #include "xobject.h"
 | |
| #include "xtable.h"
 | |
| #include "tabext.h"
 | |
| #include "javaconn.h"
 | |
| #include "resource.h"
 | |
| #include "valblk.h"
 | |
| #include "osutil.h"
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| extern "C" HINSTANCE s_hModule;           // Saved module handle
 | |
| #endif   // _WIN32
 | |
| #define nullptr 0
 | |
| 
 | |
| //TYPCONV GetTypeConv();
 | |
| //int GetConvSize();
 | |
| extern char *JvmPath;   // The connect_jvm_path global variable value
 | |
| extern char *ClassPath; // The connect_class_path global variable value
 | |
| 
 | |
| char *GetPluginDir(void);
 | |
| char *GetMessageDir(void);
 | |
| char *GetJavaWrapper(void);		// The connect_java_wrapper variable value
 | |
| extern MYSQL_PLUGIN_IMPORT char lc_messages_dir[FN_REFLEN];
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Static JAVAConn objects.                                           */
 | |
| /***********************************************************************/
 | |
| void  *JAVAConn::LibJvm = NULL;
 | |
| CRTJVM JAVAConn::CreateJavaVM = NULL;
 | |
| GETJVM JAVAConn::GetCreatedJavaVMs = NULL;
 | |
| #if defined(_DEBUG)
 | |
| GETDEF JAVAConn::GetDefaultJavaVMInitArgs = NULL;
 | |
| #endif   // _DEBUG
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Some macro's (should be defined elsewhere to be more accessible)   */
 | |
| /***********************************************************************/
 | |
| #if defined(_DEBUG)
 | |
| #define ASSERT(f)          assert(f)
 | |
| #define DEBUG_ONLY(f)      (f)
 | |
| #else   // !_DEBUG
 | |
| #define ASSERT(f)          ((void)0)
 | |
| #define DEBUG_ONLY(f)      ((void)0)
 | |
| #endif  // !_DEBUG
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  JAVAConn construction/destruction.                                 */
 | |
| /***********************************************************************/
 | |
| JAVAConn::JAVAConn(PGLOBAL g, PCSZ wrapper)
 | |
| {
 | |
| 	m_G = g;
 | |
| 	jvm = nullptr;            // Pointer to the JVM (Java Virtual Machine)
 | |
| 	env = nullptr;            // Pointer to native interface
 | |
| 	jdi = nullptr;						// Pointer to the java wrapper class
 | |
| 	job = nullptr;						// The java wrapper class object
 | |
| 	errid = nullptr;
 | |
| 	DiscFunc = "Disconnect";
 | |
| 	Msg = NULL;
 | |
| 	m_Wrap = (wrapper) ? wrapper : GetJavaWrapper();
 | |
| 
 | |
| 	if (!strchr(m_Wrap, '/')) {
 | |
| 		// Add the wrapper package name
 | |
| 		char *wn = (char*)PlugSubAlloc(g, NULL, strlen(m_Wrap) + 10);
 | |
| 		m_Wrap = strcat(strcpy(wn, "wrappers/"), m_Wrap);
 | |
| 	} // endif m_Wrap
 | |
| 
 | |
| 	fp = NULL;
 | |
| 	m_Opened = false;
 | |
| 	m_Connected = false;
 | |
| 	m_Rows = 0;
 | |
| //*m_ErrMsg = '\0';
 | |
| } // end of JAVAConn
 | |
| 
 | |
| //JAVAConn::~JAVAConn()
 | |
| //  {
 | |
| //if (Connected())
 | |
| //  EndCom();
 | |
| 
 | |
| //  } // end of ~JAVAConn
 | |
| char *JAVAConn::GetUTFString(jstring s)
 | |
| {
 | |
| 	char *str;
 | |
| 	const char *utf = env->GetStringUTFChars(s, nullptr);
 | |
| 
 | |
| 	str = PlugDup(m_G, utf);
 | |
| 	env->ReleaseStringUTFChars(s, utf);
 | |
| 	env->DeleteLocalRef(s);
 | |
| 	return str;
 | |
| }	// end of GetUTFString
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Screen for errors.                                                 */
 | |
| /***********************************************************************/
 | |
| bool JAVAConn::Check(jint rc)
 | |
| {
 | |
| 	jstring s;
 | |
| 
 | |
| 	if (env->ExceptionCheck()) {
 | |
| 		jthrowable exc = env->ExceptionOccurred();
 | |
| 		jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"),
 | |
| 			"toString", "()Ljava/lang/String;");
 | |
| 
 | |
| 		if (exc != nullptr && tid != nullptr) {
 | |
| 			s = (jstring)env->CallObjectMethod(exc, tid);
 | |
| 			Msg = GetUTFString(s);
 | |
| 		} else
 | |
| 			Msg = "Exception occurred";
 | |
| 
 | |
| 		env->ExceptionClear();
 | |
| 	} else if (rc < 0) {
 | |
| 		s = (jstring)env->CallObjectMethod(job, errid);
 | |
| 		Msg = GetUTFString(s);
 | |
| 	} else
 | |
| 		Msg = NULL;
 | |
| 
 | |
| 	return (Msg != NULL);
 | |
| } // end of Check
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Get MethodID if not exists yet.                                    */
 | |
| /***********************************************************************/
 | |
| bool JAVAConn::gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig)
 | |
| {
 | |
| 	if (mid == nullptr) {
 | |
| 		mid = env->GetMethodID(jdi, name, sig);
 | |
| 
 | |
| 		if (Check()) {
 | |
| 			snprintf(g->Message, sizeof(g->Message), "%s", Msg);
 | |
| 			return true;
 | |
| 		} else
 | |
| 			return false;
 | |
| 
 | |
| 	} else
 | |
| 		return false;
 | |
| 
 | |
| } // end of gmID
 | |
| 
 | |
| #if 0
 | |
| /***********************************************************************/
 | |
| /*  Utility routine.                                                   */
 | |
| /***********************************************************************/
 | |
| int JAVAConn::GetMaxValue(int n)
 | |
| {
 | |
| 	jint      m;
 | |
| 	jmethodID maxid = nullptr;
 | |
| 
 | |
| 	if (gmID(m_G, maxid, "GetMaxValue", "(I)I"))
 | |
| 		return -1;
 | |
| 
 | |
| 	// call method
 | |
| 	if (Check(m = env->CallIntMethod(job, maxid, n)))
 | |
| 		htrc("GetMaxValue: %s", Msg);
 | |
| 
 | |
| 	return (int)m;
 | |
| } // end of GetMaxValue
 | |
| #endif // 0
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Reset the JVM library.                                             */
 | |
| /***********************************************************************/
 | |
| void JAVAConn::ResetJVM(void)
 | |
| {
 | |
| 	if (LibJvm) {
 | |
| #if defined(_WIN32)
 | |
| 		FreeLibrary((HMODULE)LibJvm);
 | |
| #else   // !_WIN32
 | |
| 		dlclose(LibJvm);
 | |
| #endif  // !_WIN32
 | |
| 		LibJvm = NULL;
 | |
| 		CreateJavaVM = NULL;
 | |
| 		GetCreatedJavaVMs = NULL;
 | |
| #if defined(_DEBUG)
 | |
| 		GetDefaultJavaVMInitArgs = NULL;
 | |
| #endif   // _DEBUG
 | |
| 	} // endif LibJvm
 | |
| 
 | |
| } // end of ResetJVM
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Dynamically link the JVM library.                                  */
 | |
| /*  The purpose of this function is to allow using the CONNECT plugin  */
 | |
| /*  for other table types when the Java JDK is not installed.          */
 | |
| /***********************************************************************/
 | |
| bool JAVAConn::GetJVM(PGLOBAL g)
 | |
| {
 | |
| 	int ntry;
 | |
| 
 | |
| 	if (!LibJvm) {
 | |
| 		char soname[512];
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| 		for (ntry = 0; !LibJvm && ntry < 3; ntry++) {
 | |
| 			if (!ntry && JvmPath) {
 | |
| 				snprintf(soname, sizeof(soname), "%s\\jvm.dll", JvmPath);
 | |
| 
 | |
| 				ntry = 3;		 // No other try
 | |
| 			} else if (ntry < 2 && getenv("JAVA_HOME")) {
 | |
| 				safe_strcpy(soname, sizeof(soname), getenv("JAVA_HOME"));
 | |
| 
 | |
| 				if (ntry == 1)
 | |
| 					safe_strcat(soname, sizeof(soname), "\\jre");
 | |
| 
 | |
| 				safe_strcat(soname, sizeof(soname), "\\bin\\client\\jvm.dll");
 | |
| 			} else {
 | |
| 				// Try to find it through the registry
 | |
| 				char version[16];
 | |
| 				char javaKey[64] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
 | |
| 				LONG  rc;
 | |
| 				DWORD BufferSize = 16;
 | |
| 
 | |
| 				safe_strcpy(soname, sizeof(soname), "jvm.dll");		// In case it fails
 | |
| 
 | |
| 				if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "CurrentVersion",
 | |
| 					RRF_RT_ANY, NULL, (PVOID)&version, &BufferSize)) == ERROR_SUCCESS) {
 | |
| 					safe_strcat(javaKey, sizeof(javaKey), "\\");
 | |
| 					safe_strcat(javaKey, sizeof(javaKey), version);
 | |
| 					BufferSize = sizeof(soname);
 | |
| 
 | |
| 					if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "RuntimeLib",
 | |
| 						RRF_RT_ANY, NULL, (PVOID)&soname, &BufferSize)) != ERROR_SUCCESS)
 | |
| 						printf("RegGetValue: rc=%ld\n", rc);
 | |
| 
 | |
| 				} // endif rc
 | |
| 
 | |
| 				ntry = 3;		 // Try this only once
 | |
| 			} // endelse
 | |
| 
 | |
| 			// Load the desired shared library
 | |
| 			LibJvm = LoadLibrary(soname);
 | |
| 		}	// endfor ntry
 | |
| 
 | |
| 		// Get the needed entries
 | |
| 		if (!LibJvm) {
 | |
| 			char  buf[256];
 | |
| 			DWORD rc = GetLastError();
 | |
| 
 | |
| 			FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
 | |
| 										FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
 | |
| 				            (LPTSTR)buf, sizeof(buf), NULL);
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(DLL_LOAD_ERROR)": %s", rc,
 | |
| 							 soname, buf);
 | |
| 		} else if (!(CreateJavaVM = (CRTJVM)GetProcAddress((HINSTANCE)LibJvm,
 | |
| 			                                       "JNI_CreateJavaVM"))) {
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(PROCADD_ERROR), GetLastError(), "JNI_CreateJavaVM");
 | |
| 			FreeLibrary((HMODULE)LibJvm);
 | |
| 			LibJvm = NULL;
 | |
| 		} else if (!(GetCreatedJavaVMs = (GETJVM)GetProcAddress((HINSTANCE)LibJvm,
 | |
| 			                                       "JNI_GetCreatedJavaVMs"))) {
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(PROCADD_ERROR), GetLastError(), "JNI_GetCreatedJavaVMs");
 | |
| 			FreeLibrary((HMODULE)LibJvm);
 | |
| 			LibJvm = NULL;
 | |
| #if defined(_DEBUG)
 | |
| 		} else if (!(GetDefaultJavaVMInitArgs = (GETDEF)GetProcAddress((HINSTANCE)LibJvm,
 | |
| 			                                       "JNI_GetDefaultJavaVMInitArgs"))) {
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(PROCADD_ERROR), GetLastError(),
 | |
| 				"JNI_GetDefaultJavaVMInitArgs");
 | |
| 			FreeLibrary((HMODULE)LibJvm);
 | |
| 			LibJvm = NULL;
 | |
| #endif   // _DEBUG
 | |
| 		} // endif LibJvm
 | |
| #else   // !_WIN32
 | |
| 		const char *error = NULL;
 | |
| 
 | |
| 		for (ntry = 0; !LibJvm && ntry < 2; ntry++) {
 | |
| 			if (!ntry && JvmPath) {
 | |
| 				snprintf(soname, sizeof(soname), "%s/libjvm.so", JvmPath);
 | |
| 				ntry = 2;
 | |
| 			} else if (!ntry && getenv("JAVA_HOME")) {
 | |
| 				// TODO: Replace i386 by a better guess
 | |
| 				snprintf(soname, sizeof(soname), "%s/jre/lib/i386/client/libjvm.so",
 | |
| 								 getenv("JAVA_HOME"));
 | |
| 			} else {	 // Will need LD_LIBRARY_PATH to be set
 | |
| 				safe_strcpy(soname, sizeof(soname), "libjvm.so");
 | |
| 				ntry = 2;
 | |
| 			} // endelse
 | |
| 
 | |
| 			LibJvm = dlopen(soname, RTLD_LAZY);
 | |
| 		} // endfor ntry
 | |
| 
 | |
| 			// Load the desired shared library
 | |
| 		if (!LibJvm) {
 | |
| 			error = dlerror();
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(SHARED_LIB_ERR), soname, SVP(error));
 | |
| 		} else if (!(CreateJavaVM = (CRTJVM)dlsym(LibJvm, "JNI_CreateJavaVM"))) {
 | |
| 			error = dlerror();
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(GET_FUNC_ERR), "JNI_CreateJavaVM", SVP(error));
 | |
| 			dlclose(LibJvm);
 | |
| 			LibJvm = NULL;
 | |
| 		} else if (!(GetCreatedJavaVMs = (GETJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) {
 | |
| 			error = dlerror();
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error));
 | |
| 			dlclose(LibJvm);
 | |
| 			LibJvm = NULL;
 | |
| #if defined(_DEBUG)
 | |
| 		} else if (!(GetDefaultJavaVMInitArgs = (GETDEF)dlsym(LibJvm,
 | |
| 			"JNI_GetDefaultJavaVMInitArgs"))) {
 | |
| 			error = dlerror();
 | |
| 			snprintf(g->Message, sizeof(g->Message), MSG(GET_FUNC_ERR), "JNI_GetDefaultJavaVMInitArgs", SVP(error));
 | |
| 			dlclose(LibJvm);
 | |
| 			LibJvm = NULL;
 | |
| #endif   // _DEBUG
 | |
| 		} // endif LibJvm
 | |
| #endif  // !_WIN32
 | |
| 
 | |
| 	} // endif LibJvm
 | |
| 
 | |
| 	return LibJvm == NULL;
 | |
| } // end of GetJVM
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Open: connect to a data source.                                    */
 | |
| /***********************************************************************/
 | |
| bool JAVAConn::Open(PGLOBAL g)
 | |
| {
 | |
|          bool		 brc = true;
 | |
| 	jboolean jt = (trace(1));
 | |
| 
 | |
| 	// Link or check whether jvm library was linked
 | |
| 	if (GetJVM(g))
 | |
| 		return true;
 | |
| 
 | |
| 	// Firstly check whether the jvm was already created
 | |
| 	JavaVM* jvms[1];
 | |
| 	jsize   jsz;
 | |
| 	jint    rc = GetCreatedJavaVMs(jvms, 1, &jsz);
 | |
| 
 | |
| 	if (rc == JNI_OK && jsz == 1) {
 | |
| 		// jvm already existing
 | |
| 		jvm = jvms[0];
 | |
| 		rc = jvm->AttachCurrentThread((void**)&env, nullptr);
 | |
| 
 | |
| 		if (rc != JNI_OK) {
 | |
| 			snprintf(g->Message, sizeof(g->Message), "Cannot attach jvm to the current thread");
 | |
| 			return true;
 | |
| 		} // endif rc
 | |
| 
 | |
| 	} else {
 | |
| 		/*******************************************************************/
 | |
| 		/*  Create a new jvm																							 */
 | |
| 		/*******************************************************************/
 | |
| 		PSTRG    jpop = new(g)STRING(g, 512, "-Djava.class.path=.");
 | |
| 		char    *cp = NULL;
 | |
| 		char     sep;
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| 		sep = ';';
 | |
| #define N 1
 | |
| 		//#define N 2
 | |
| 		//#define N 3
 | |
| #else
 | |
| 		sep = ':';
 | |
| #define N 1
 | |
| #endif
 | |
| 
 | |
| 		// Add wrappers jar files 
 | |
| 		AddJars(jpop, sep);
 | |
| 
 | |
| 		//================== prepare loading of Java VM ============================
 | |
| 		JavaVMInitArgs vm_args;                        // Initialization arguments
 | |
| 		JavaVMOption* options = new JavaVMOption[N];   // JVM invocation options
 | |
| 
 | |
| 		// where to find java .class
 | |
| 		if (ClassPath && *ClassPath) {
 | |
| 			jpop->Append(sep);
 | |
| 			jpop->Append(ClassPath);
 | |
| 		}	// endif ClassPath
 | |
| 
 | |
| 		jpop->Append(sep);
 | |
| 		jpop->Append(GetMessageDir());
 | |
| 		jpop->Append("JdbcInterface.jar");
 | |
| 
 | |
| #if defined(MONGO_SUPPORT)
 | |
| 		jpop->Append(sep);
 | |
| 		jpop->Append(GetMessageDir());
 | |
| 		jpop->Append("Mongo3.jar");
 | |
| 		jpop->Append(sep);
 | |
| 		jpop->Append(GetMessageDir());
 | |
| 		jpop->Append("Mongo2.jar");
 | |
| #endif   // MONGO_SUPPORT
 | |
| 
 | |
| 		if ((cp = getenv("CLASSPATH"))) {
 | |
| 			jpop->Append(sep);
 | |
| 			jpop->Append(cp);
 | |
| 		} // endif cp
 | |
| 
 | |
| 		if (trace(1)) {
 | |
| 			htrc("ClassPath=%s\n", ClassPath ? ClassPath : "null");
 | |
| 			htrc("CLASSPATH=%s\n", cp ? cp : "null");
 | |
| 			htrc("%s\n", jpop->GetStr());
 | |
| 		} // endif trace
 | |
| 
 | |
| 		options[0].optionString = jpop->GetStr();
 | |
| #if N == 2
 | |
| 		options[1].optionString = "-Xcheck:jni";
 | |
| #endif
 | |
| #if N == 3
 | |
| 		options[1].optionString = "-Xms256M";
 | |
| 		options[2].optionString = "-Xmx512M";
 | |
| #endif
 | |
| #if defined(_DEBUG)
 | |
| 		vm_args.version = JNI_VERSION_1_2;             // minimum Java version
 | |
| 		rc = GetDefaultJavaVMInitArgs(&vm_args);
 | |
| #else
 | |
| 		vm_args.version = JNI_VERSION_1_6;             // minimum Java version
 | |
| #endif   // _DEBUG
 | |
| 		vm_args.nOptions = N;                          // number of options
 | |
| 		vm_args.options = options;
 | |
| 		vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail
 | |
| 
 | |
| 		//=============== load and initialize Java VM and JNI interface =============
 | |
| 		rc = CreateJavaVM(&jvm, (void**)&env, &vm_args);  // YES !!
 | |
| 		delete[] options;    // we then no longer need the initialisation options.
 | |
| 
 | |
| 		switch (rc) {
 | |
| 			case JNI_OK:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "VM successfully created");
 | |
| 				brc = false;
 | |
| 				break;
 | |
| 			case JNI_ERR:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "Initialising JVM failed: unknown error");
 | |
| 				break;
 | |
| 			case JNI_EDETACHED:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "Thread detached from the VM");
 | |
| 				break;
 | |
| 			case JNI_EVERSION:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "JNI version error");
 | |
| 				break;
 | |
| 			case JNI_ENOMEM:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "Not enough memory");
 | |
| 				break;
 | |
| 			case JNI_EEXIST:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "VM already created");
 | |
| 				break;
 | |
| 			case JNI_EINVAL:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "Invalid arguments");
 | |
| 				break;
 | |
| 			default:
 | |
| 				snprintf(g->Message, sizeof(g->Message), "Unknown return code %d", (int)rc);
 | |
| 				break;
 | |
| 		} // endswitch rc
 | |
| 
 | |
| 		if (trace(1))
 | |
| 			htrc("%s\n", g->Message);
 | |
| 
 | |
| 		if (brc)
 | |
| 			return true;
 | |
| 
 | |
| 		//=============== Display JVM version ===============
 | |
| 		jint ver = env->GetVersion();
 | |
| 		printf("JVM Version %d.%d\n", ((ver >> 16) & 0x0f), (ver & 0x0f));
 | |
| 	} // endif rc
 | |
| 
 | |
| 	// try to find the java wrapper class
 | |
| 	jdi = env->FindClass(m_Wrap);
 | |
| 
 | |
| 	if (jdi == nullptr) {
 | |
| 		snprintf(g->Message, sizeof(g->Message), "ERROR: class %s not found!", m_Wrap);
 | |
| 		return true;
 | |
| 	} // endif jdi
 | |
| 
 | |
| #if 0		// Suppressed because it does not make any usable change
 | |
| 	if (b && jpath && *jpath) {
 | |
| 		// Try to add that path the the jvm class path
 | |
| 		jmethodID alp = env->GetStaticMethodID(jdi, "addLibraryPath",
 | |
| 			"(Ljava/lang/String;)I");
 | |
| 
 | |
| 		if (alp == nullptr) {
 | |
| 			env->ExceptionDescribe();
 | |
| 			env->ExceptionClear();
 | |
| 		} else {
 | |
| 			char *msg;
 | |
| 			jstring path = env->NewStringUTF(jpath);
 | |
| 			rc = env->CallStaticIntMethod(jdi, alp, path);
 | |
| 
 | |
| 			if ((msg = Check(rc))) {
 | |
| 				snprintf(g->Message, sizeof(g->Message), msg);
 | |
| 				env->DeleteLocalRef(path);
 | |
| 				return RC_FX;
 | |
| 			} else switch (rc) {
 | |
| 				case JNI_OK:
 | |
| 					printf("jpath added\n");
 | |
| 					break;
 | |
| 				case JNI_EEXIST:
 | |
| 					printf("jpath already exist\n");
 | |
| 					break;
 | |
| 				case JNI_ERR:
 | |
| 				default:
 | |
| 					snprintf(g->Message, sizeof(g->Message), "Error adding jpath");
 | |
| 					env->DeleteLocalRef(path);
 | |
| 					return RC_FX;
 | |
| 			}	// endswitch rc
 | |
| 
 | |
| 			env->DeleteLocalRef(path);
 | |
| 		}	// endif alp
 | |
| 
 | |
| 	}	// endif jpath
 | |
| #endif // 0
 | |
| 
 | |
| 	// if class found, continue
 | |
| 	jmethodID ctor = env->GetMethodID(jdi, "<init>", "(Z)V");
 | |
| 
 | |
| 	if (ctor == nullptr) {
 | |
| 		snprintf(g->Message, sizeof(g->Message), "ERROR: %s constructor not found!", m_Wrap);
 | |
| 		return true;
 | |
| 	} else
 | |
| 		job = env->NewObject(jdi, ctor, jt);
 | |
| 
 | |
| 	if (job == nullptr) {
 | |
| 		snprintf(g->Message, sizeof(g->Message), "%s class object not constructed!", m_Wrap);
 | |
| 		return true;
 | |
| 	} // endif job
 | |
| 
 | |
| 	// If the object is successfully constructed, 
 | |
| 	// we can then search for the method we want to call, 
 | |
| 	// and invoke it for the object:
 | |
| 	errid = env->GetMethodID(jdi, "GetErrmsg", "()Ljava/lang/String;");
 | |
| 
 | |
| 	if (env->ExceptionCheck()) {
 | |
| 		snprintf(g->Message, sizeof(g->Message), "ERROR: method GetErrmsg() not found!");
 | |
| 		env->ExceptionDescribe();
 | |
| 		env->ExceptionClear();
 | |
| 		return true;
 | |
| 	} // endif Check
 | |
| 
 | |
| 	/*********************************************************************/
 | |
| 	/*  Link a Fblock. This make possible to automatically close it      */
 | |
| 	/*  in case of error (throw).                                        */
 | |
| 	/*********************************************************************/
 | |
| 	PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
 | |
| 
 | |
| 	fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
 | |
| 	fp->Type = TYPE_FB_JAVA;
 | |
| 	fp->Fname = NULL;
 | |
| 	fp->Next = dbuserp->Openlist;
 | |
| 	dbuserp->Openlist = fp;
 | |
| 	fp->Count = 1;
 | |
| 	fp->Length = 0;
 | |
| 	fp->Memory = NULL;
 | |
| 	fp->Mode = MODE_ANY;
 | |
| 	fp->File = this;
 | |
| 	fp->Handle = 0;
 | |
| 
 | |
| 	m_Opened = true;
 | |
| 	return false;
 | |
| } // end of Open
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Disconnect connection                                              */
 | |
| /***********************************************************************/
 | |
| void JAVAConn::Close()
 | |
| {
 | |
| 	jint rc;
 | |
| 
 | |
| 	if (m_Connected) {
 | |
| 		jmethodID did = nullptr;
 | |
| 
 | |
| 		// Could have been detached in case of join
 | |
| 		rc = jvm->AttachCurrentThread((void**)&env, nullptr);
 | |
| 
 | |
| 		if (gmID(m_G, did, DiscFunc, "()I"))
 | |
| 			printf("%s\n", Msg);
 | |
| 		else if (Check(env->CallIntMethod(job, did)))
 | |
| 			printf("%s: %s\n", DiscFunc, Msg);
 | |
| 
 | |
| 		m_Connected = false;
 | |
| 	}	// endif m_Connected
 | |
| 
 | |
| 	if ((rc = jvm->DetachCurrentThread()) != JNI_OK)
 | |
| 		printf("DetachCurrentThread: rc=%d\n", (int)rc);
 | |
| 
 | |
| 	if (fp)
 | |
| 		fp->Count = 0;
 | |
| 
 | |
| 	m_Opened = false;
 | |
| } // end of Close
 | 
