From c1944d134ebffcf518596301c2b3e3d3de75aae3 Mon Sep 17 00:00:00 2001 From: Vedant Tewari Date: Sun, 15 Sep 2024 16:46:10 -0500 Subject: [PATCH] Updated documentation, fixed exception handling --- DEPENDENCIES.md | 2 +- NEWS | 4 +++- libcob/java.c | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index a94327471..db892996f 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -128,4 +128,4 @@ Support for JNI (Java Native Interface) is provided by: The JDK is distributed under various open-source licenses depending on the vendor and version. Common licenses include the GNU General Public License (GPL) and the Oracle Binary Code License Agreement. -To enable JNI support, ensure that the JDK is installed on your system, and set the appropriate environment variables (e.g., JAVA_HOME) to point to the JDK installation directory. \ No newline at end of file + To enable JNI support, ensure that the JDK is installed on your system, and set the appropriate environment variables (e.g., JAVA_HOME) to point to the JDK installation directory. \ No newline at end of file diff --git a/NEWS b/NEWS index 3b2393747..1ef4ce7b7 100644 --- a/NEWS +++ b/NEWS @@ -20,7 +20,9 @@ NEWS - user visible changes -*- outline -*- * New GnuCOBOL features -** Initial support for Java interoperability through JNI (new optional dependency JDK) +** Initial support for Java interoperability through JNI (optional dependency JDK): Java Interoperability: Added initial support for calling + Java methods from COBOL programs via the Java Native Interface (JNI). This feature currently supports static Java methods with no parameters, while handling parameters and return values will be introduced in future updates. The system detects missing Java classes and malformed method names and provides proper error handling. COBOL developers can now use ON EXCEPTION and NOT ON EXCEPTION clauses with Java calls. JNI support is an optional feature that requires the Java Development Kit (JDK) to be installed on the system. Use the --with-java configure option to enable it, and ensure that the JAVA_HOME environment variable is set at runtime to locate the JDK. Without JNI, the runtime will function as usual but Java-related COBOL calls (e.g., CALL "Java..") will not be available + ** file handling: added backends for ODBC (so far PostgrSQL, MySQL, SQLite, MSSQL) and OCI, along with new directory COB_SCHEMA_DIR containing the necessary internal schema files to match the file definition to the diff --git a/libcob/java.c b/libcob/java.c index 3e9840300..af1e69b81 100644 --- a/libcob/java.c +++ b/libcob/java.c @@ -115,9 +115,39 @@ call_java (const cob_java_handle *method_handle) (*env)->CallStaticVoidMethod(env, method_handle->cls, method_handle->mid, NULL); - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); + jthrowable exception = (*env)->ExceptionOccurred(env); + if(exception) { + jclass throwable = (*env)->FindClass(env, "java/lang/Throwable"); + jmethodID getMessage = (*env)->GetMethodID(env, + throwable, "getMessage", "()Ljava/lang/String;"); + if(getMessage != NULL) { + jstring message = (jstring)(*env)->CallObjectMethod(env, exception, getMessage); + const char *messageChars = (*env)->GetStringUTFChars(env, message, NULL); + cob_runtime_error(_("Java exception: %s"), messageChars); + (*env)->ReleaseStringUTFChars(env, message, messageChars); + (*env)->DeleteLocalRef(env, message); + } + jclass stringWriter = (*env)->FindClass(env, "java/io/StringWriter"); + jclass printWriter = (*env)->FindClass(env, "java/io/PrintWriter"); + jobject stringWriterObj = (*env)->NewObject(env, + stringWriter, + (*env)->GetMethodID(env, stringWriter, "", "()V")); + jobject printWriterObj = (*env)->NewObject(env, + printWriter, + (*env)->GetMethodID(env, printWriter, "", "(Ljava/io/Writer;)V"), + stringWriterObj); + jmethodID printStackTrace = (*env)->GetMethodID(env, throwable, "printStackTrace", "(Ljava/io/PrintWriter;)V"); + (*env)->CallVoidMethod(env, exception, printStackTrace, printWriter); + jmethodID toString = (*env)->GetMethodID(env, stringWriter, "toString", "()Ljava/lang/String;"); + jstring stackTrace = (jstring)(*env)->CallObjectMethod(env, stringWriterObj, toString); + const char *stackTraceChars = (*env)->GetStringUTFChars(env, stackTrace, NULL); + cob_runtime_error(_("Java stack trace: %s"), stackTraceChars); + + (*env)->ReleaseStringUTFChars(env, stackTrace, stackTraceChars); + (*env)->DeleteLocalRef(env, stackTrace); + (*env)->DeleteLocalRef(env, stringWriterObj); + (*env)->DeleteLocalRef(env, printWriterObj); + (*env)->DeleteLocalRef(env, exception); } }