mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
618 lines
19 KiB
C++
618 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, err = false;
|
|
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
|
|
|
|
// All wrappers are pre-compiled in JavaWrappers.jar in the share dir
|
|
jpop->Append(sep);
|
|
jpop->Append(GetMessageDir());
|
|
jpop->Append("JavaWrappers.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
|