mirror of
https://github.com/HDFGroup/hdf5.git
synced 2026-09-25 04:09:44 +03:00
FFM build requires Java 25, Jextract 25. Generates FFM bindings during configure. JNI is default when the requirements are not met or can be forced. Presets added for maven and FFM - JNI is default selection. Enhanced Maven options will work with either JNI or FFM New Workflows for testing and maven uploads. Extensive documentation changes for java.
488 lines
16 KiB
C
488 lines
16 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* 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 LICENSE 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. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#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"))) { \
|
|
printf("THROWEXCEPTION FATAL ERROR: GetMethodID failed\n"); \
|
|
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); \
|
|
} \
|
|
\
|
|
if (NULL == (ex = ENVPTR->NewObjectA(ENVONLY, jc, jm, (jvalue *)(args)))) { \
|
|
printf("THROWEXCEPTION FATAL ERROR: Class %s: Creation failed\n", (className)); \
|
|
CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); \
|
|
} \
|
|
\
|
|
if (ENVPTR->Throw(ENVONLY, (jthrowable)ex) < 0) { \
|
|
printf("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 = fopen(file, "a+"))) {
|
|
H5Eprint2(H5E_DEFAULT, stream);
|
|
fclose(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 *)calloc((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)
|
|
free(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 */
|