blob: cb8b296cb8a51741bfbff0e8f8bea9427004b74e [file] [log] [blame]
/** @name jni_utils.cpp
-----------------------------------------------------------------------------
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-----------------------------------------------------------------------------
Description:
-----------------------------------------------------------------------------
07/26/2000 Initial creation
-------------------------------------------------------------------------- */
/*@{*/ /* Doc++ Group */
/* ----------------------------------------------------------------------- */
/* Include dependencies */
/* ----------------------------------------------------------------------- */
#include "uima/pragmas.hpp"
#include "uima/jni_utils.hpp"
#include "uima/macros.h"
/* ----------------------------------------------------------------------- */
/* Constants */
/* ----------------------------------------------------------------------- */
#define JAVA_CLASS_INTERNALTAFEXCEPTION "org/apache/uima/uimacpp/InternalTafException"
#define JUIMA_FIELD_CPPENGINEPOINTER "cppEnginePointer"
/* ----------------------------------------------------------------------- */
/* Forward declarations */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Types / Classes */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Implementation */
/* ----------------------------------------------------------------------- */
using namespace std;
jfieldID JNIUtils::getFieldID(JNIEnv* jeEnv, jobject jo, char const * sig, char const * cpszFieldID) {
jclass clazz = jeEnv->GetObjectClass(jo);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
jfieldID jFID = jeEnv->GetFieldID(clazz, cpszFieldID, sig);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
return jFID;
}
long JNIUtils::getLongField(JNIEnv* jeEnv, jobject jo, char const * cpszFieldName) {
assertWithMsg(sizeof(long) == sizeof(jlong), "Port required");
jlong jValue = jeEnv->GetLongField(jo, getFieldID(jeEnv, jo, "J", cpszFieldName) );
ASSERT_NO_JNI_EXCEPTION(jeEnv);
return (long) jValue;
}
void JNIUtils::setLongField(JNIEnv* jeEnv, jobject jo, char const * cpszFieldName, long l) {
assertWithMsg(sizeof(long) == sizeof(jlong), "Port required");
jeEnv->SetLongField(jo, getFieldID(jeEnv, jo, "J", cpszFieldName), (jlong) l);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
}
/*
void JNIUtils::throwNewInternalException(JNIEnv* jeEnv,
icu::UnicodeString errorMessage) {
throwNewInternalException(jeEnv, errorMessage, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION);
}
*/
void JNIUtils::throwNewInternalException(JNIEnv* jeEnv,
icu::UnicodeString errorMessage,
uima::TyErrorId errorId) {
jclass clazz = jeEnv->FindClass(JAVA_CLASS_INTERNALTAFEXCEPTION);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
// get the constructor which takes a message and an errorID
jmethodID jmExcConstructor = jeEnv->GetMethodID(clazz, "<init>", "(Ljava/lang/String;J)V");
ASSERT_NO_JNI_EXCEPTION(jeEnv);
assertWithMsg( sizeof(jchar) == sizeof(UChar), "Port required");
assertWithMsg( sizeof(uima::TyErrorId) <= sizeof(jlong), "Port required");
jstring jsErrorMessage = jeEnv->NewString( (const jchar*) errorMessage.getBuffer(), errorMessage.length());
jthrowable jtIkfInternalException = (jthrowable) jeEnv->NewObject(clazz, jmExcConstructor, jsErrorMessage, (jlong) errorId);
jeEnv->Throw(jtIkfInternalException);
}
void JNIUtils::throwNewInternalException(JNIEnv* jeEnv, uima::Exception & rException) {
string sExc = rException.asString();
icu::UnicodeString usExc(sExc.c_str(), sExc.length());
throwNewInternalException(jeEnv, usExc, rException.getErrorInfo().getErrorId());
}
void JNIUtils::throwNewInternalException(JNIEnv* jeEnv, uima::ErrorInfo const & errInfo) {
string sExc = errInfo.asString();
icu::UnicodeString usExc(sExc.c_str(), sExc.length());
throwNewInternalException(jeEnv, usExc, errInfo.getErrorId());
}
void JNIUtils::setCppInstance(JNIEnv* jeEnv,
jobject joJTaf,
uima::JNIInstance* pInstance) {
jclass clazz = jeEnv->GetObjectClass(joJTaf);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
// get the field of clazz named "cppEnginePointer" which is a long
jfieldID fid = jeEnv->GetFieldID(clazz, JUIMA_FIELD_CPPENGINEPOINTER, "J");
ASSERT_NO_JNI_EXCEPTION(jeEnv);
assertWithMsg( sizeof(void*) <= sizeof(jlong), "Port required");
jeEnv->SetLongField(joJTaf, fid, (jlong) pInstance);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
}
uima::JNIInstance* JNIUtils::getCppInstance(JNIEnv* jeEnv,
jobject joJTaf) {
jclass clazz = jeEnv->GetObjectClass(joJTaf);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
jfieldID fid = jeEnv->GetFieldID(clazz, JUIMA_FIELD_CPPENGINEPOINTER, "J");
ASSERT_NO_JNI_EXCEPTION(jeEnv);
jlong jlPointer = jeEnv->GetLongField(joJTaf, fid);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
assertWithMsg( sizeof(void*) <= sizeof(jlong), "Port required");
return(uima::JNIInstance*) jlPointer;
}
jobjectArray JNIUtils::createStringArray(JNIEnv* jeEnv, vector<uima::UnicodeStringRef> const & crVec) {
jobjectArray joArr = NULL;
size_t uiLen = crVec.size();
ASSERT_NO_JNI_EXCEPTION(jeEnv);
jclass jcStringClass = jeEnv->FindClass("java/lang/String");
assert( jcStringClass != NULL );
ASSERT_NO_JNI_EXCEPTION(jeEnv);
joArr = jeEnv->NewObjectArray( uiLen, jcStringClass, NULL );
ASSERT_NO_JNI_EXCEPTION(jeEnv);
size_t i;
for (i=0; i<uiLen; ++i) {
UIMA_TPRINT("Copying string " << i);
JavaString str(jeEnv, crVec[i]);
UIMA_TPRINT("Entering string " << i << " into array");
jeEnv->SetObjectArrayElement(joArr, (jsize) i, str.getJObject());
ASSERT_NO_JNI_EXCEPTION(jeEnv);
}
return joArr;
}
jintArray JNIUtils::createIntArray(JNIEnv* jeEnv, vector<uima::internal::SerializedCAS::TyNum> const & crVec) {
jintArray jiArr = NULL;
assert( sizeof(uima::internal::SerializedCAS::TyNum) == sizeof(jint) );
size_t uiLength = crVec.size();
// assert( uiLength > 0);
jiArr = jeEnv->NewIntArray(uiLength);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#ifdef TEMP_DISABLED
// call to SetIntArrayRegion() assumes that vector iterators
// are implemented as pointers
// check at least that they have equal size by the following assert
assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
jeEnv->SetIntArrayRegion(jiArr, 0, uiLength, (jint*) crVec.begin());
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif
if (uiLength > 0) {
// since the above code does not work for msc7,
// allocate a new array and copy it by hand
jint * pJIntArray = new jint[uiLength];
size_t i=0;
vector<uima::internal::SerializedCAS::TyNum>::const_iterator cit;
for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
pJIntArray[i++] = (jint) *cit;
}
assert( i == uiLength );
jeEnv->SetIntArrayRegion(jiArr, 0, uiLength, pJIntArray);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
delete pJIntArray;
}
return jiArr;
}
void JNIUtils::createIntVector(JNIEnv* jeEnv, jintArray array, vector<uima::internal::SerializedCAS::TyNum> & rResult) {
size_t uiLen = jeEnv->GetArrayLength(array);
rResult.resize(uiLen);
jeEnv->PushLocalFrame( uiLen );
jboolean jbCopy;
jint * pArray = jeEnv->GetIntArrayElements(array, & jbCopy);
size_t i;
for (i=0; i<uiLen; ++i) {
rResult[i] = pArray[i];
}
jeEnv->ReleaseIntArrayElements(array, pArray, JNI_ABORT);
jeEnv->PopLocalFrame(NULL);
}
void JNIUtils::createStringVector(JNIEnv* jeEnv, jobjectArray joArray, vector<uima::UnicodeStringRef> & rResult, vector<icu::UnicodeString> & rStringPool) {
size_t uiLen = jeEnv->GetArrayLength(joArray);
rResult.resize(uiLen);
rStringPool.resize(uiLen);
jeEnv->PushLocalFrame( uiLen );
// cout << __FILE__ << __LINE__ << ": len: " << uiLen << endl;
size_t i;
for (i=0; i<uiLen; ++i) {
jobject jo = jeEnv->GetObjectArrayElement(joArray, i);
if (jo != 0) {
jstring js = (jstring) jo;
JNIUString uString(jeEnv, js);
uima::UnicodeStringRef ref = uString.toUStrPtrLenPair();
// cout << __FILE__ << __LINE__ << ":" << i << " string " << uString.toUStrPtrLenPair() << endl;
rStringPool[i] = UnicodeString( ref.getBuffer(), ref.length() );
rResult[i] = uima::UnicodeStringRef(rStringPool[i]);
} else {
rResult[i] = uima::UnicodeStringRef();
}
}
jeEnv->PopLocalFrame(NULL);
}
jbyteArray JNIUtils::createByteArray(JNIEnv* jeEnv, vector<char> const & crVec) {
jbyteArray jiArr = NULL;
size_t uiLength = crVec.size();
// assert( uiLength > 0);
jiArr = jeEnv->NewByteArray(uiLength);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#ifdef TEMP_DISABLED
// call to SetIntArrayRegion() assumes that vector iterators
// are implemented as pointers
// check at least that they have equal size by the following assert
//assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
jeEnv->SetByteArrayRegion(jiArr, 0, uiLength, (jbyte*) crVec.begin());
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif
if (uiLength > 0) {
// since the above code does not work for msc7,
// allocate a new array and copy it by hand
jbyte * pJByteArray = new jbyte[uiLength];
size_t i=0;
vector<char>::const_iterator cit;
for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
pJByteArray[i++] = (jbyte) *cit;
}
assert( i == uiLength );
jeEnv->SetByteArrayRegion(jiArr, 0, uiLength, pJByteArray);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
delete pJByteArray;
}
return jiArr;
}
jshortArray JNIUtils::createShortArray(JNIEnv* jeEnv, vector<short> const & crVec) {
jshortArray jiArr = NULL;
size_t uiLength = crVec.size();
// assert( uiLength > 0);
jiArr = jeEnv->NewShortArray(uiLength);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#ifdef TEMP_DISABLED
// call to SetIntArrayRegion() assumes that vector iterators
// are implemented as pointers
// check at least that they have equal size by the following assert
//assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
jeEnv->SetShortArrayRegion(jiArr, 0, uiLength, (jshort*) crVec.begin());
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif
if (uiLength > 0) {
// since the above code does not work for msc7,
// allocate a new array and copy it by hand
jshort * pJShortArray = new jshort[uiLength];
size_t i=0;
vector<short>::const_iterator cit;
for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
pJShortArray[i++] = (jshort) *cit;
}
assert( i == uiLength );
jeEnv->SetShortArrayRegion(jiArr, 0, uiLength, pJShortArray);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
delete pJShortArray;
}
return jiArr;
}
jlongArray JNIUtils::createLongArray(JNIEnv* jeEnv, vector<INT64> const & crVec) {
jlongArray jiArr = NULL;
size_t uiLength = crVec.size();
// assert( uiLength > 0);
jiArr = jeEnv->NewLongArray(uiLength);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#ifdef TEMP_DISABLED
// call to SetIntArrayRegion() assumes that vector iterators
// are implemented as pointers
// check at least that they have equal size by the following assert
//assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
jeEnv->SetLongArrayRegion(jiArr, 0, uiLength, (jlong*) crVec.begin());
ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif
if (uiLength > 0) {
// since the above code does not work for msc7,
// allocate a new array and copy it by hand
jlong * pJLongArray = new jlong[uiLength];
size_t i=0;
vector<INT64>::const_iterator cit;
for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
pJLongArray[i++] = (jlong) *cit;
}
assert( i == uiLength );
jeEnv->SetLongArrayRegion(jiArr, 0, uiLength, pJLongArray);
ASSERT_NO_JNI_EXCEPTION(jeEnv);
delete pJLongArray;
}
return jiArr;
}
void JNIUtils::createByteVector(JNIEnv* jeEnv, jbyteArray array, vector<char> & rResult) {
size_t uiLen = jeEnv->GetArrayLength(array);
rResult.resize(uiLen);
jeEnv->PushLocalFrame( uiLen );
jboolean jbCopy;
jbyte * pArray = jeEnv->GetByteArrayElements(array, & jbCopy);
size_t i;
for (i=0; i<uiLen; ++i) {
rResult[i] = pArray[i];
}
jeEnv->ReleaseByteArrayElements(array,pArray, JNI_ABORT);
jeEnv->PopLocalFrame(NULL);
}
void JNIUtils::createShortVector(JNIEnv* jeEnv, jshortArray array, vector<short> & rResult) {
size_t uiLen = jeEnv->GetArrayLength(array);
rResult.resize(uiLen);
jeEnv->PushLocalFrame( uiLen );
jboolean jbCopy;
jshort * pArray = jeEnv->GetShortArrayElements(array, & jbCopy);
size_t i;
for (i=0; i<uiLen; ++i) {
rResult[i] = pArray[i];
}
jeEnv->ReleaseShortArrayElements(array,pArray, JNI_ABORT);
jeEnv->PopLocalFrame(NULL);
}
void JNIUtils::createLongVector(JNIEnv* jeEnv, jlongArray array, vector<INT64> & rResult) {
size_t uiLen = jeEnv->GetArrayLength(array);
rResult.resize(uiLen);
jeEnv->PushLocalFrame( uiLen );
jboolean jbCopy;
jlong * pArray = jeEnv->GetLongArrayElements(array, & jbCopy);
size_t i;
for (i=0; i<uiLen; ++i) {
rResult[i] = pArray[i];
}
jeEnv->ReleaseLongArrayElements(array,pArray, JNI_ABORT);
jeEnv->PopLocalFrame(NULL);
}
/* ----------------------------------------------------------------------- */
/*@}*/ /* e-o-Doc++ Group */
/* <EOF> */