in language-extensions/java/src/JavaArgContainer.cpp [792:1193]
void JavaArgContainer::CreateOdbcArgObject(
JNIEnv *env,
jobject jObj,
JavaArg *arg)
{
// Auto cleanup any local references
// 1 reference for the class
// 2 references for the additional classes/temp objects required by other types (guid, string)
//
AutoJniLocalFrame jFrame(env, 2);
switch (arg->GetType())
{
case SQL_C_SLONG:
{
jclass objectClass = env->FindClass("java/lang/Integer");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/Integer");
jmethodID getValueMethod = JniHelper::FindMethod(env,
objectClass,
"intValue",
"()I");
jint val = env->CallIntMethod(jObj, getValueMethod);
JniHelper::ThrowOnJavaException(env);
arg->m_value = new int(static_cast<int>(val));
arg->m_strLenOrInd = sizeof(int);
break;
}
case SQL_C_BIT:
{
jclass objectClass = env->FindClass("java/lang/Boolean");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/Boolean");
jmethodID getValueMethod = JniHelper::FindMethod(env,
objectClass,
"booleanValue",
"()Z");
jboolean val = env->CallBooleanMethod(jObj, getValueMethod);
JniHelper::ThrowOnJavaException(env);
arg->m_value = new bool(static_cast<bool>(val));
arg->m_strLenOrInd = sizeof(bool);
break;
}
case SQL_C_DOUBLE:
{
jclass objectClass = env->FindClass("java/lang/Double");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/Double");
jmethodID getValueMethod = JniHelper::FindMethod(env,
objectClass,
"doubleValue",
"()D");
jdouble val = env->CallDoubleMethod(jObj, getValueMethod);
JniHelper::ThrowOnJavaException(env);
arg->m_value = new double(static_cast<double>(val));
arg->m_strLenOrInd = sizeof(double);
break;
}
case SQL_C_FLOAT:
{
jclass objectClass = env->FindClass("java/lang/Float");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/Float");
jmethodID getValueMethod = JniHelper::FindMethod(env,
objectClass,
"floatValue",
"()F");
jfloat val = env->CallFloatMethod(jObj, getValueMethod);
JniHelper::ThrowOnJavaException(env);
arg->m_value = new float(static_cast<float>(val));
arg->m_strLenOrInd = sizeof(float);
break;
}
case SQL_C_SBIGINT:
{
jclass objectClass = env->FindClass("java/lang/Long");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/Long");
jmethodID getValueMethod = JniHelper::FindMethod(env,
objectClass,
"longValue",
"()J");
jlong val = env->CallLongMethod(jObj, getValueMethod);
JniHelper::ThrowOnJavaException(env);
arg->m_value = new long long(static_cast<long long>(val));
arg->m_strLenOrInd = sizeof(long long);
break;
}
case SQL_C_UTINYINT:
{
jclass objectClass = env->FindClass("java/lang/Short");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/Short");
jmethodID getValueMethod = JniHelper::FindMethod(env,
objectClass,
"shortValue",
"()S");
jshort val = env->CallShortMethod(jObj, getValueMethod);
JniHelper::ThrowOnJavaException(env);
if (0 <= val && val <= 255)
{
arg->m_value = new unsigned char(static_cast<unsigned char>(val));
arg->m_strLenOrInd = sizeof(char);
}
else
{
throw runtime_error(
"The value of output parameter #" +
to_string(arg->GetId()) +
" is out of range for tinyint data type");
}
break;
}
case SQL_C_SSHORT:
{
jclass objectClass = env->FindClass("java/lang/Short");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/Short");
jmethodID getValueMethod = JniHelper::FindMethod(env,
objectClass,
"shortValue",
"()S");
jshort val = env->CallShortMethod(jObj, getValueMethod);
JniHelper::ThrowOnJavaException(env);
arg->m_value = new short(static_cast<short>(val));
arg->m_strLenOrInd = sizeof(short);
break;
}
case SQL_C_GUID:
{
jclass stringClass = env->FindClass("java/lang/String");
ValidateOutputClass(env, arg->GetId(), jObj, stringClass, "java/lang/String");
jclass uuidClass = env->FindClass("java/util/UUID");
jmethodID fromStringMethod = env->GetStaticMethodID(uuidClass,
"fromString",
"(Ljava/lang/String;)Ljava/util/UUID;");
jmethodID lsbMethod = JniHelper::FindMethod(env,
uuidClass,
"getLeastSignificantBits",
"()J");
jmethodID msbMethod = JniHelper::FindMethod(env,
uuidClass,
"getMostSignificantBits",
"()J");
arg->m_value = JniTypeHelper::JavaStringToGuidStruct(
env,
reinterpret_cast<jstring>(jObj),
uuidClass,
fromStringMethod,
lsbMethod,
msbMethod);
arg->m_strLenOrInd = sizeof(SQLGUID);
break;
}
case SQL_C_BINARY:
{
jclass objectClass = env->FindClass("[B");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "[B");
// Get the size of the parameter
//
jbyteArray byteArray = reinterpret_cast<jbyteArray>(jObj);
jsize jNumOfBytes = env->GetArrayLength(byteArray);
// Allocate space for the parameter
//
std::unique_ptr<jbyte[]> tempArr(new jbyte[jNumOfBytes]);
// Copy the value to the output buffer
//
jbyte *byteData = static_cast<jbyte*>(env->GetPrimitiveArrayCritical(byteArray, nullptr));
if (byteData)
{
memcpy(tempArr.get(),
byteData,
jNumOfBytes);
env->ReleasePrimitiveArrayCritical(byteArray, byteData, 0);
}
else
{
JniHelper::ThrowOnJavaException(env);
}
arg->m_value = tempArr.release();
arg->m_strLenOrInd = jNumOfBytes;
break;
}
case SQL_C_CHAR:
{
jclass objectClass = env->FindClass("java/lang/String");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/String");
jstring jStr = reinterpret_cast<jstring>(jObj);
const jstring jUtf8Str = env->NewStringUTF("UTF-8");
JniHelper::ThrowOnJavaException(env);
jmethodID jMethod = JniHelper::FindMethod(env,
objectClass,
"getBytes",
"(Ljava/lang/String;)[B");
// Get the string in UTF-8 encoding
//
jbyteArray jUtf8BytesArr =
static_cast<jbyteArray>(env->CallObjectMethod(jStr, jMethod, jUtf8Str));
JniHelper::ThrowOnJavaException(env);
// Get the size of the string
//
jsize jNumOfBytes = env->GetArrayLength(static_cast<jarray>(jUtf8BytesArr));
// Allocate space for the string
//
std::unique_ptr<jbyte[]> tempArr(new jbyte[jNumOfBytes]);
// Copy the string to the output buffer
//
jbyte *byteData =
static_cast<jbyte*>(env->GetPrimitiveArrayCritical(jUtf8BytesArr, nullptr));
if (byteData)
{
memcpy(tempArr.get(),
byteData,
jNumOfBytes);
env->ReleasePrimitiveArrayCritical(jUtf8BytesArr, byteData, 0);
}
else
{
JniHelper::ThrowOnJavaException(env);
}
arg->m_value = tempArr.release();
arg->m_strLenOrInd = jNumOfBytes;
break;
}
case SQL_C_WCHAR:
{
jclass objectClass = env->FindClass("java/lang/String");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/lang/String");
jstring jStr = reinterpret_cast<jstring>(jObj);
// Get the size of the string
//
jsize strLenInChars = env->GetStringLength(jStr);
// Allocate space for the string
//
std::unique_ptr<jchar[]> tempArr(new jchar[strLenInChars]);
// Copy the string to the output buffer
//
env->GetStringRegion(jStr, 0, strLenInChars, tempArr.get());
SQLINTEGER strLenInBytes = static_cast<SQLINTEGER>(strLenInChars * sizeof(jchar));
arg->m_value = tempArr.release();
arg->m_strLenOrInd = strLenInBytes;
break;
}
case SQL_C_TYPE_DATE:
{
jclass objectClass = env->FindClass("java/sql/Date");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/sql/Date");
jmethodID dateToStringMethod = env->GetMethodID(objectClass,
"toString",
"()Ljava/lang/String;");
jmethodID dateValueOfMethod = env->GetStaticMethodID(objectClass,
"valueOf",
"(Ljava/lang/String;)Ljava/sql/Date;");
std::unique_ptr<SQL_DATE_STRUCT> tempValue(new SQL_DATE_STRUCT());
JniTypeHelper::JavaSqlDateToDateStruct(
env,
jObj,
objectClass,
dateToStringMethod,
dateValueOfMethod,
*tempValue.get());
arg->m_value = tempValue.release();
arg->m_strLenOrInd = sizeof(SQL_DATE_STRUCT);
break;
}
case SQL_C_TYPE_TIMESTAMP:
{
jclass objectClass = env->FindClass("java/sql/Timestamp");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/sql/Timestamp");
jmethodID tsToStringMethod = JniHelper::FindMethod(env,
objectClass,
"toString",
"()Ljava/lang/String;");
jmethodID tsGetNanosMethod = JniHelper::FindMethod(env, objectClass, "getNanos", "()I");
jmethodID tsValueOfMethod = env->GetStaticMethodID(objectClass,
"valueOf",
"(Ljava/lang/String;)Ljava/sql/Timestamp;");
JniHelper::ThrowOnJavaException(env);
std::unique_ptr<SQL_TIMESTAMP_STRUCT> tempValue(new SQL_TIMESTAMP_STRUCT());
JniTypeHelper::JavaTimestampToTimestampStruct(
env,
jObj,
objectClass,
tsToStringMethod,
tsGetNanosMethod,
tsValueOfMethod,
*tempValue.get());
arg->m_value = tempValue.release();
arg->m_strLenOrInd = sizeof(SQL_TIMESTAMP_STRUCT);
break;
}
case SQL_C_NUMERIC:
{
jclass objectClass = env->FindClass("java/math/BigDecimal");
ValidateOutputClass(env, arg->GetId(), jObj, objectClass, "java/math/BigDecimal");
jmethodID bigDecUnscaledValue = JniHelper::FindMethod(env,
objectClass,
"unscaledValue",
"()Ljava/math/BigInteger;");
jclass bigIntegerClass = env->FindClass("java/math/BigInteger");
jmethodID bigIntToByteArr = JniHelper::FindMethod(env, bigIntegerClass, "toByteArray", "()[B");
jmethodID bigIntSignum = JniHelper::FindMethod(env, bigIntegerClass, "signum", "()I");
jmethodID bigIntAbs = JniHelper::FindMethod(env,
bigIntegerClass,
"abs",
"()Ljava/math/BigInteger;");
std::unique_ptr<SQL_NUMERIC_STRUCT> tempValue(new SQL_NUMERIC_STRUCT());
JniTypeHelper::BigDecimalToNumericStruct(
env,
jObj,
static_cast<SQLCHAR>(arg->GetSize()),
arg->GetDecimalDigits(),
bigDecUnscaledValue,
bigIntToByteArr,
bigIntSignum,
bigIntAbs,
"output parameter ID " + std::to_string(arg->GetId()),
*tempValue.get());
arg->m_value = tempValue.release();
arg->m_strLenOrInd = sizeof(SQL_NUMERIC_STRUCT);
break;
}
default:
throw runtime_error("Unsupported output parameter type encountered");
}
}