summaryrefslogtreecommitdiffstats
path: root/java/src/jni/exceptionImp.c
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/jni/exceptionImp.c')
-rw-r--r--java/src/jni/exceptionImp.c493
1 files changed, 493 insertions, 0 deletions
diff --git a/java/src/jni/exceptionImp.c b/java/src/jni/exceptionImp.c
new file mode 100644
index 0000000..464f457
--- /dev/null
+++ b/java/src/jni/exceptionImp.c
@@ -0,0 +1,493 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://www.hdfgroup.org/licenses. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * For details of the HDF libraries, see the HDF Documentation at:
+ * http://hdfgroup.org/HDF5/doc/
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/***********/
+/* Headers */
+/***********/
+
+#include "hdf5.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "jni.h"
+#include "h5jni.h"
+#include "exceptionImp.h"
+
+extern H5E_auto2_t efunc;
+extern void *edata;
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/*
+ * The list of error messages in the system is kept as an array of
+ * error_code/message pairs, one for major error numbers and another for
+ * minor error numbers.
+ */
+typedef struct H5E_major_mesg_t {
+ hid_t error_code;
+ const char *str;
+} H5E_major_mesg_t;
+
+typedef struct H5E_minor_mesg_t {
+ hid_t error_code;
+ const char *str;
+} H5E_minor_mesg_t;
+
+/* major and minor error numbers */
+typedef struct H5E_num_t {
+ hid_t maj_num;
+ hid_t min_num;
+} H5E_num_t;
+
+/********************/
+/* Local Macros */
+/********************/
+
+#define THROWEXCEPTION(className, args) \
+ { \
+ jmethodID jm; \
+ jclass jc; \
+ jobject ex; \
+ \
+ if (NULL == (jc = ENVPTR->FindClass(ENVONLY, (className)))) \
+ CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); \
+ \
+ if (NULL == (jm = ENVPTR->GetMethodID(ENVONLY, jc, "<init>", "(Ljava/lang/String;)V"))) { \
+ HDprintf("THROWEXCEPTION FATAL ERROR: GetMethodID failed\n"); \
+ CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); \
+ } \
+ \
+ if (NULL == (ex = ENVPTR->NewObjectA(ENVONLY, jc, jm, (jvalue *)(args)))) { \
+ HDprintf("THROWEXCEPTION FATAL ERROR: Class %s: Creation failed\n", (className)); \
+ CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); \
+ } \
+ \
+ if (ENVPTR->Throw(ENVONLY, (jthrowable)ex) < 0) { \
+ HDprintf("THROWEXCEPTION FATAL ERROR: Class %s: Throw failed\n", (className)); \
+ CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); \
+ } \
+ }
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static const char *defineHDF5LibraryException(hid_t maj_num);
+static jboolean H5JNIErrorClass(JNIEnv *env, const char *message, const char *className);
+
+/* get the major and minor error numbers on the top of the error stack */
+static herr_t
+walk_error_callback(unsigned n, const H5E_error2_t *err_desc, void *_err_nums)
+{
+ H5E_num_t *err_nums = (H5E_num_t *)_err_nums;
+
+ UNUSED(n);
+
+ if (err_desc) {
+ err_nums->maj_num = err_desc->maj_num;
+ err_nums->min_num = err_desc->min_num;
+ } /* end if */
+
+ return 0;
+} /* end walk_error_callback() */
+
+/*
+ * Class: hdf_hdf5lib_exceptions_HDF5Library
+ * Method: H5error_off
+ * Signature: ()I
+ *
+ */
+JNIEXPORT jint JNICALL
+Java_hdf_hdf5lib_H5_H5error_1off(JNIEnv *env, jclass clss)
+{
+ UNUSED(env);
+ UNUSED(clss);
+
+ if (H5Eget_auto2(H5E_DEFAULT, &efunc, &edata) < 0)
+ return -1;
+
+ if (H5Eset_auto2(H5E_DEFAULT, NULL, NULL) < 0)
+ return -1;
+
+ return 0;
+} /* end Java_hdf_hdf5lib_H5_H5error_1off() */
+
+/*
+ * Class: hdf_hdf5lib_exceptions_HDF5Library
+ * Method: H5error_on
+ * Signature: ()V
+ *
+ */
+JNIEXPORT void JNICALL
+Java_hdf_hdf5lib_H5_H5error_1on(JNIEnv *env, jclass clss)
+{
+ UNUSED(env);
+ UNUSED(clss);
+
+ H5Eset_auto2(H5E_DEFAULT, efunc, edata);
+} /* end Java_hdf_hdf5lib_H5_H5error_1on() */
+
+/*
+ * Class: hdf_hdf5lib_exceptions_HDFLibraryException
+ * Method: printStackTrace0
+ * Signature: (Ljava/lang/Object;)V
+ *
+ * Call the HDF5 library to print the HDF5 error stack to 'file_name'.
+ */
+JNIEXPORT void JNICALL
+Java_hdf_hdf5lib_exceptions_HDF5LibraryException_printStackTrace0(JNIEnv *env, jobject obj, jstring file_name)
+{
+ FILE *stream = NULL;
+ const char *file = NULL;
+
+ UNUSED(obj);
+
+ if (NULL == file_name) {
+ H5Eprint2(H5E_DEFAULT, stderr);
+ }
+ else {
+ PIN_JAVA_STRING(ENVONLY, file_name, file, NULL, "printStackTrace0: file name not pinned");
+
+ if ((stream = HDfopen(file, "a+"))) {
+ H5Eprint2(H5E_DEFAULT, stream);
+ HDfclose(stream);
+ }
+ }
+
+done:
+ if (file)
+ UNPIN_JAVA_STRING(ENVONLY, file_name, file);
+
+ return;
+} /* end Java_hdf_hdf5lib_exceptions_HDF5LibraryException_printStackTrace0() */
+
+/*
+ * Class: hdf_hdf5lib_exceptions_HDFLibraryException
+ * Method: _getMajorErrorNumber
+ * Signature: ()J
+ *
+ * Extract the HDF5 major error number from the HDF5 error stack.
+ */
+JNIEXPORT jlong JNICALL
+Java_hdf_hdf5lib_exceptions_HDF5LibraryException__1getMajorErrorNumber(JNIEnv *env, jobject obj)
+{
+ H5E_num_t err_nums;
+
+ UNUSED(env);
+ UNUSED(obj);
+
+ err_nums.maj_num = 0;
+ err_nums.min_num = 0;
+
+ if (H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, walk_error_callback, &err_nums) < 0)
+ return -1;
+
+ return err_nums.maj_num;
+} /* end Java_hdf_hdf5lib_exceptions_HDF5LibraryException__1getMajorErrorNumber() */
+
+/*
+ * Class: hdf_hdf5lib_exceptions_HDFLibraryException
+ * Method: _getMinorErrorNumber
+ * Signature: ()J
+ *
+ * Extract the HDF5 minor error number from the HDF5 error stack.
+ */
+JNIEXPORT jlong JNICALL
+Java_hdf_hdf5lib_exceptions_HDF5LibraryException__1getMinorErrorNumber(JNIEnv *env, jobject obj)
+{
+ H5E_num_t err_nums;
+
+ UNUSED(env);
+ UNUSED(obj);
+
+ err_nums.maj_num = 0;
+ err_nums.min_num = 0;
+
+ if (H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, walk_error_callback, &err_nums) < 0)
+ return -1;
+
+ return err_nums.min_num;
+} /* end Java_hdf_hdf5lib_exceptions_HDF5LibraryException__1getMinorErrorNumber() */
+
+/*
+ * Routine to raise particular Java exceptions from C.
+ */
+static jboolean
+H5JNIErrorClass(JNIEnv *env, const char *message, const char *className)
+{
+ jstring str;
+ char *args[2];
+ jboolean retVal = JNI_FALSE;
+
+ if (NULL == (str = ENVPTR->NewStringUTF(ENVONLY, message)))
+ CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
+
+ args[0] = (char *)str;
+ args[1] = 0;
+
+ THROWEXCEPTION(className, args);
+
+ retVal = JNI_TRUE;
+
+done:
+ return retVal;
+} /* end H5JNIErrorClass() */
+
+/*
+ * Create and throw an 'outOfMemoryException'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5outOfMemory(JNIEnv *env, const char *message)
+{
+ return H5JNIErrorClass(env, message, "java/lang/OutOfMemoryError");
+} /* end h5outOfMemory() */
+
+/*
+ * Create and throw an 'AssertionError'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5assertion(JNIEnv *env, const char *message)
+{
+ return H5JNIErrorClass(env, message, "java/lang/AssertionError");
+} /* end h5assertion() */
+
+/*
+ * A fatal error in a JNI call
+ * Create and throw an 'InternalError'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5JNIFatalError(JNIEnv *env, const char *message)
+{
+ return H5JNIErrorClass(env, message, "java/lang/InternalError");
+} /* end h5JNIFatalError() */
+
+/*
+ * A NULL argument in an HDF5 call
+ * Create and throw an 'NullPointerException'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5nullArgument(JNIEnv *env, const char *message)
+{
+ return H5JNIErrorClass(env, message, "java/lang/NullPointerException");
+} /* end h5nullArgument() */
+
+/*
+ * A bad argument in an HDF5 call
+ * Create and throw an 'IllegalArgumentException'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5badArgument(JNIEnv *env, const char *message)
+{
+ return H5JNIErrorClass(env, message, "java/lang/IllegalArgumentException");
+} /* end h5badArgument() */
+
+/*
+ * Some feature Not implemented yet
+ * Create and throw an 'UnsupportedOperationException'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5unimplemented(JNIEnv *env, const char *message)
+{
+ return H5JNIErrorClass(env, message, "java/lang/UnsupportedOperationException");
+} /* end h5unimplemented() */
+
+/* h5raiseException(). This routine is called to generate
+ * an arbitrary Java exception with a particular message.
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5raiseException(JNIEnv *env, const char *message, const char *exception)
+{
+ return H5JNIErrorClass(env, message, exception);
+} /* end h5raiseException() */
+
+/*
+ * h5libraryError() determines the HDF5 major error code
+ * and creates and throws the appropriate sub-class of
+ * HDF5LibraryException(). This routine should be called
+ * whenever a call to the HDF5 library fails, i.e., when
+ * the return is -1.
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean
+h5libraryError(JNIEnv *env)
+{
+ const char *exception = NULL;
+ H5E_type_t error_msg_type;
+ H5E_num_t exceptionNumbers;
+ jstring str = NULL;
+ ssize_t msg_size = 0;
+ hid_t min_num;
+ hid_t maj_num;
+ hid_t stk_id = H5I_INVALID_HID;
+ char *args[2];
+ char *msg_str = NULL;
+ jboolean retVal = JNI_FALSE;
+
+ exceptionNumbers.maj_num = 0;
+ exceptionNumbers.min_num = 0;
+
+ /* Save current stack contents for future use */
+ if ((stk_id = H5Eget_current_stack()) >= 0)
+ /* This will clear current stack */
+ if (H5Ewalk2(stk_id, H5E_WALK_DOWNWARD, walk_error_callback, &exceptionNumbers) < 0)
+ goto done;
+
+ maj_num = exceptionNumbers.maj_num;
+ min_num = exceptionNumbers.min_num;
+
+ /*
+ * TODO: handle < 0 case.
+ */
+
+ /*
+ * No error detected in HDF5 error stack.
+ */
+ if (!maj_num && !min_num)
+ goto done;
+
+ exception = defineHDF5LibraryException(maj_num);
+
+ /* get the length of the name */
+ if ((msg_size = H5Eget_msg(min_num, NULL, NULL, 0)) < 0)
+ goto done;
+
+ if (msg_size > 0) {
+ if (NULL == (msg_str = (char *)HDcalloc((size_t)msg_size + 1, sizeof(char))))
+ H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5libraryerror: failed to allocate buffer for error message");
+
+ if ((msg_size = H5Eget_msg(min_num, &error_msg_type, msg_str, (size_t)msg_size + 1)) < 0)
+ goto done;
+ msg_str[msg_size] = '\0';
+
+ if (NULL == (str = ENVPTR->NewStringUTF(ENVONLY, msg_str)))
+ CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE);
+ }
+ else
+ str = NULL;
+
+ if (stk_id >= 0)
+ H5Eset_current_stack(stk_id);
+
+ args[0] = (char *)str;
+ args[1] = 0;
+
+ THROWEXCEPTION(exception, args);
+
+ retVal = JNI_TRUE;
+
+done:
+ if (msg_str)
+ HDfree(msg_str);
+
+ return retVal;
+} /* end h5libraryError() */
+
+/*
+ * defineHDF5LibraryException() returns the name of the sub-class
+ * which goes with an HDF5 error code.
+ */
+static const char *
+defineHDF5LibraryException(hid_t maj_num)
+{
+ hid_t err_num = maj_num;
+
+ if (H5E_ARGS == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5FunctionArgumentException";
+ else if (H5E_RESOURCE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5ResourceUnavailableException";
+ else if (H5E_INTERNAL == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5InternalErrorException";
+ else if (H5E_FILE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5FileInterfaceException";
+ else if (H5E_IO == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5LowLevelIOException";
+ else if (H5E_FUNC == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5FunctionEntryExitException";
+ else if (H5E_ID == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5IdException";
+ else if (H5E_CACHE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5MetaDataCacheException";
+ else if (H5E_BTREE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5BtreeException";
+ else if (H5E_SYM == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5SymbolTableException";
+ else if (H5E_HEAP == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5HeapException";
+ else if (H5E_OHDR == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5ObjectHeaderException";
+ else if (H5E_DATATYPE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5DatatypeInterfaceException";
+ else if (H5E_DATASPACE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5DataspaceInterfaceException";
+ else if (H5E_DATASET == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5DatasetInterfaceException";
+ else if (H5E_STORAGE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5DataStorageException";
+ else if (H5E_PLIST == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5PropertyListInterfaceException";
+ else if (H5E_ATTR == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5AttributeException";
+ else if (H5E_PLINE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5DataFiltersException";
+ else if (H5E_EFL == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5ExternalFileListException";
+ else if (H5E_REFERENCE == err_num)
+ return "hdf/hdf5lib/exceptions/HDF5ReferenceException";
+
+ return "hdf/hdf5lib/exceptions/HDF5LibraryException";
+} /* end defineHDF5LibraryException() */
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif /* __cplusplus */