blob: 3dada9b7eb2f12ac0a849a037001132eddc48e2d [file] [log] [blame]
/** \file internal_jedii_engine.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:
-----------------------------------------------------------------------------
-------------------------------------------------------------------------- */
//#define DEBUG_VERBOSE
/* ----------------------------------------------------------------------- */
/* Include dependencies */
/* ----------------------------------------------------------------------- */
#include "uima/pragmas.hpp"
#include "uima/trace.hpp"
#include "uima/envvar.hpp"
#include "uima/macros.h"
#include "uima/macros.h"
#include "uima/stltools.hpp"
#include "uima/msg.h"
#include "uima/internal_jedii_engine.hpp"
#include "uima/internal_casserializer.hpp"
#include "uima/internal_casdeserializer.hpp"
#include "uima/annotator_context.hpp"
#include "uima/resmgr.hpp"
/* ----------------------------------------------------------------------- */
/* Constants */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Forward declarations */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Types / Classes */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Implementation */
/* ----------------------------------------------------------------------- */
/*
There's a lot of JNI code in here. If you are interested in the details you should
consult some book or go to
http://java.sun.com/j2se/1.3/docs/guide/jni/spec/jniTOC.doc.html
*/
using namespace std;
namespace uima {
namespace internal {
UIMA_EXC_CLASSIMPLEMENT(JavaException, Exception);
#define USED_JAVA_VERSION JNI_VERSION_1_2
// not NLS enabled !!!!!!!
icu::UnicodeString javaErrorToString(jint res) {
switch (res) {
case JNI_OK:
return "no error";
case JNI_ERR:
return "unknown error";
case JNI_EDETACHED:
return "thread detached from the VM";
case JNI_EVERSION:
return "JNI version error";
case JNI_ENOMEM:
return "not enough memory";
case JNI_EEXIST:
return "VM already created";
case JNI_EINVAL:
return "invalid arguments";
default:
char buf[2056];
sprintf(buf, "%d", res);
return icu::UnicodeString(buf);
}
}
JEDIIEngine::JEDIIEngine(AnnotatorContext & anc, bool bOwnsANC,
bool bOwnsTAESpecififer, uima::internal::CASDefinition & casdef, bool ownsCasDef)
: EngineBase(anc, bOwnsANC, bOwnsTAESpecififer, casdef, ownsCasDef),
iv_vm(NULL),
iv_env(NULL),
iv_obj(NULL),
iv_createdVM(false),
iv_initializeMethod(NULL),
iv_processMethod(NULL),
iv_destroyMethod(NULL),
iv_getLastExceptionStringMethod(NULL),
iv_getHeapMethod(NULL),
iv_getIndexedFSsMethod(NULL),
iv_getStringTableMethod(NULL),
iv_getVersionMethod(NULL),
iv_isPrimitive(0),
iv_JVMDllLoader(NULL),
iv_createJavaVMFunc(NULL),
iv_getCreatedJavaVMsFunc(NULL) {
}
JEDIIEngine::~JEDIIEngine() {
destroyIfNeeded();
}
void JEDIIEngine::checkForUnexpectedJNIException() {
jthrowable exc = iv_env->ExceptionOccurred();
if (exc != NULL) {
#ifndef NDEBUG
iv_env->ExceptionDescribe();
#endif
// if exception was thrown, get class name of exception plus the message
// and throw a C++ exception
// don't check for JNI exceptions in these calls because exception is already thrown
jclass throwableClass = iv_env->FindClass("java/lang/Throwable");
jmethodID getClassID = iv_env->GetMethodID(throwableClass, "getClass", "()Ljava/lang/Class;");
assert( getClassID != NULL);
jclass classClass = iv_env->FindClass("java/lang/Class");
assert( classClass != NULL);
jmethodID getNameID = iv_env->GetMethodID(classClass, "getName", "()Ljava/lang/String;");
assert( getNameID != NULL );
jobject classObject = iv_env->CallObjectMethod(exc, getClassID);
assert ( classObject != NULL );
jstring msg = (jstring) iv_env->CallObjectMethod(classObject, getNameID);
jboolean copied;
jchar const * jc = iv_env->GetStringChars(msg, &copied);
assert( jc != NULL );
size_t len = iv_env->GetStringLength(msg);
icu::UnicodeString usMsg((UChar const *)jc, len);
iv_env->ReleaseStringChars(msg, jc);
// msg now contains the class name
// add getMessage() of the throwable
assert( throwableClass != NULL );
jmethodID getMessageID = iv_env->GetMethodID(throwableClass, "getMessage", "()Ljava/lang/String;");
assert ( getMessageID != NULL );
msg = (jstring) iv_env->CallObjectMethod(exc, getMessageID);
if ( msg != NULL ) {
usMsg.append(": ");
jc = iv_env->GetStringChars(msg, &copied);
len = iv_env->GetStringLength(msg);
usMsg.append( icu::UnicodeString((UChar const *)jc, len) );
iv_env->ReleaseStringChars(msg, jc);
}
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_JAVA_EXCEPTION,
ErrorMessage(UIMA_MSG_ID_EXC_UNKNOWN_JAVA_EXCEPTION, usMsg),
UIMA_MSG_ID_EXCON_PROCESSING_JAVA_TAE,
ErrorInfo::unrecoverable);
}
}
// create a new Java int[] from a C++ vector
jintArray JEDIIEngine::createJIntArray(vector<internal::SerializedCAS::TyNum> const & v) {
jintArray result = iv_env->NewIntArray(v.size());
checkForUnexpectedJNIException();
size_t i;
for (i=0; i<v.size(); ++i) {
jint n = v[i];
iv_env->SetIntArrayRegion(result, i,1, &n );
checkForUnexpectedJNIException();
#ifndef NDEBUG
jint m;
iv_env->GetIntArrayRegion(result, i, 1, &m );
checkForUnexpectedJNIException();
assert( n == m );
#endif
}
return result;
}
// create a new Java byte[] from a C++ vector
jbyteArray JEDIIEngine::createJByteArray(vector<char> const & v) {
jbyteArray result = iv_env->NewByteArray(v.size());
checkForUnexpectedJNIException();
size_t i;
for (i=0; i<v.size(); ++i) {
jbyte n = v[i];
iv_env->SetByteArrayRegion(result, i,1, &n );
checkForUnexpectedJNIException();
#ifndef NDEBUG
jbyte m;
iv_env->GetByteArrayRegion(result, i, 1, &m );
checkForUnexpectedJNIException();
assert( n == m );
#endif
}
return result;
}
// create a new Java short[] from a C++ vector
jshortArray JEDIIEngine::createJShortArray(vector<short> const & v) {
jshortArray result = iv_env->NewShortArray(v.size());
checkForUnexpectedJNIException();
size_t i;
for (i=0; i<v.size(); ++i) {
jshort n = v[i];
iv_env->SetShortArrayRegion(result, i,1, &n );
checkForUnexpectedJNIException();
#ifndef NDEBUG
jshort m;
iv_env->GetShortArrayRegion(result, i, 1, &m );
checkForUnexpectedJNIException();
assert( n == m );
#endif
}
return result;
}
// create a new Java long[] from a C++ vector
jlongArray JEDIIEngine::createJLongArray(vector<INT64> const & v) {
jlongArray result = iv_env->NewLongArray(v.size());
checkForUnexpectedJNIException();
size_t i;
for (i=0; i<v.size(); ++i) {
jlong n = v[i];
iv_env->SetLongArrayRegion(result, i,1, &n );
checkForUnexpectedJNIException();
#ifndef NDEBUG
jlong m;
iv_env->GetLongArrayRegion(result, i, 1, &m );
checkForUnexpectedJNIException();
assert( n == m );
#endif
}
return result;
}
// create a new Object[] (which all contains java.lang.Strings) from a C++ vector
jobjectArray JEDIIEngine::createJStringArray(vector<UnicodeStringRef> const & v) {
jclass stringClass = iv_env->FindClass("java/lang/String");
checkForUnexpectedJNIException();
jobjectArray result = iv_env->NewObjectArray(v.size(), stringClass, NULL);
checkForUnexpectedJNIException();
size_t i;
for (i=0; i<v.size(); ++i) {
assertWithMsg(sizeof(UChar) == sizeof(jchar), "Port required");
jstring str = iv_env->NewString( (const jchar*)v[i].getBuffer(), v[i].length() );
checkForUnexpectedJNIException();
iv_env->SetObjectArrayElement(result, i, str);
checkForUnexpectedJNIException();
}
return result;
}
// create a java.lang.String from a C++ unicode string
jstring JEDIIEngine::createJString(UnicodeStringRef const & ref) {
assertWithMsg(sizeof(UChar) == sizeof(jchar), "Port required");
jstring result = iv_env->NewString((jchar const *) ref.getBuffer(), ref.length());
checkForUnexpectedJNIException();
return result;
}
// create a C++ vector from a Java int[]
void JEDIIEngine::createIntVector(jintArray ar, vector<internal::SerializedCAS::TyNum>& result) {
result.clear();
jsize len = iv_env->GetArrayLength(ar);
checkForUnexpectedJNIException();
jint* tempAr = new jint[len];
iv_env->GetIntArrayRegion(ar, 0, len, tempAr);
checkForUnexpectedJNIException();
result.reserve(len);
int i;
for (i=0; i<len; ++i) {
result.push_back(tempAr[i]);
}
delete[] tempAr;
}
// create a C++ string vector from a java.lang.String[]
void JEDIIEngine::createStringVector(jobjectArray ar, vector<UnicodeStringRef>& result, vector<icu::UnicodeString> & pool) {
pool.clear();
result.clear();
jsize len = iv_env->GetArrayLength(ar);
checkForUnexpectedJNIException();
result.reserve(len);
pool.reserve(len); // with this reserve, the vector will never be re-allocated, thus the internal pointer in the UnicodeString objects remain valid throughout this method!
int i;
for (i=0; i<len; ++i) {
jstring js = (jstring) iv_env->GetObjectArrayElement(ar, i);
checkForUnexpectedJNIException();
if (js != NULL) {
jboolean isCopy;
jchar const * jc = iv_env->GetStringChars(js, &isCopy);
checkForUnexpectedJNIException();
jsize strLen = iv_env->GetStringLength(js);
checkForUnexpectedJNIException();
icu::UnicodeString us((UChar const *) jc, (size_t) strLen);
iv_env->ReleaseStringChars(js, jc);
checkForUnexpectedJNIException();
pool.push_back(us);
icu::UnicodeString const & poolString = pool.back();
UnicodeStringRef uref( poolString.getBuffer(), poolString.length() );
result.push_back(uref);
} else {
UnicodeStringRef emptyURef;
result.push_back(emptyURef);
}
iv_env->DeleteLocalRef(js);
}
}
// create a C++ vector from a Java byte[]
void JEDIIEngine::createByteVector(jbyteArray ar, vector<char>& result) {
result.clear();
jsize len = iv_env->GetArrayLength(ar);
checkForUnexpectedJNIException();
jbyte* tempAr = new jbyte[len];
iv_env->GetByteArrayRegion(ar, 0, len, tempAr);
checkForUnexpectedJNIException();
result.reserve(len);
int i;
for (i=0; i<len; ++i) {
result.push_back(tempAr[i]);
}
delete[] tempAr;
}
// create a C++ vector from a Java short[]
void JEDIIEngine::createShortVector(jshortArray ar, vector<short>& result) {
result.clear();
jsize len = iv_env->GetArrayLength(ar);
checkForUnexpectedJNIException();
jshort* tempAr = new jshort[len];
iv_env->GetShortArrayRegion(ar, 0, len, tempAr);
checkForUnexpectedJNIException();
result.reserve(len);
int i;
for (i=0; i<len; ++i) {
result.push_back(tempAr[i]);
}
delete[] tempAr;
}
// create a C++ vector from a Java short[]
void JEDIIEngine::createLongVector(jlongArray ar, vector<long>& result) {
result.clear();
jsize len = iv_env->GetArrayLength(ar);
checkForUnexpectedJNIException();
jlong* tempAr = new jlong[len];
iv_env->GetLongArrayRegion(ar, 0, len, tempAr);
checkForUnexpectedJNIException();
result.reserve(len);
int i;
for (i=0; i<len; ++i) {
result.push_back(tempAr[i]);
}
delete[] tempAr;
}
template <class T>
void printVector(ostream& os, char const * c, vector<T> const & v) {
os << __FILE__ << __LINE__ << ": " << c << endl;
size_t i;
for (i=0; i<v.size(); ++i) {
os << v[i] << " ";
}
os << endl;
}
bool JEDIIEngine::isPrimitive() const {
assert( iv_isPrimitive == 1 || iv_isPrimitive == 2);
if (iv_isPrimitive == 1) {
return true;
}
return false;
}
void JEDIIEngine::handleEngineProxyError(jint rc) {
if (rc != JNI_OK) {
// some error occurred in the JEDIIEngine object
jobject excStringObj = iv_env->CallObjectMethod(iv_obj, iv_getLastExceptionStringMethod);
checkForUnexpectedJNIException();
jstring excString = (jstring) excStringObj;
jboolean isCopy;
jchar const * jc = iv_env->GetStringChars(excString, &isCopy);
checkForUnexpectedJNIException();
jsize js = iv_env->GetStringLength(excString);
checkForUnexpectedJNIException();
icu::UnicodeString us((UChar const *) jc, (size_t) js);
iv_env->ReleaseStringChars(excString, jc);
checkForUnexpectedJNIException();
handleJNIError(rc, us);
}
}
void JEDIIEngine::handleJNIError(jint rc, icu::UnicodeString const & us) {
if (rc != JNI_OK) {
ErrorMessage msg(UIMA_MSG_ID_EXC_JAVA_EXCEPTION);
msg.addParam( javaErrorToString(rc) );
msg.addParam( us);
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_JAVA_EXCEPTION,
msg,
UIMA_MSG_ID_EXCON_PROCESSING_JAVA_TAE,
ErrorInfo::unrecoverable);
}
}
void JEDIIEngine::handleJNIError(jint rc) {
if (rc != JNI_OK) {
ErrorMessage msg(UIMA_MSG_ID_EXC_JNI_CALL_FAILED);
msg.addParam( javaErrorToString(rc) );
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_JAVA_EXCEPTION,
msg,
UIMA_MSG_ID_EXCON_PROCESSING_JAVA_TAE,
ErrorInfo::unrecoverable);
}
}
void JEDIIEngine::initializeJVMFunctions() {
/*
If we linked against the jvm DLL, the following three lines would do the trick:
iv_createJavaVMFunc = (TyCreateJavaVMFunc) JNI_CreateJavaVM;
iv_getCreatedJavaVMsFunc = (TyGetCreatedJavaVMsFunc) JNI_GetCreatedJavaVMs;
return ;
*/
// names of the JVM library on the different platforms
// (APR should add the appropriate suffix)
#if defined(WIN32)
#define JVMDLL_FILE_NAME "jvm"
#else
#define JVMDLL_FILE_NAME "libjvm"
#endif
// dynamically load jvm DLL
util::Filename jvmDll(JVMDLL_FILE_NAME);
assert( iv_JVMDllLoader == NULL );
iv_JVMDllLoader = new util::DllProcLoaderFile(jvmDll);
assert( EXISTS(iv_JVMDllLoader) );
if (!iv_JVMDllLoader->isValid()) {
delete iv_JVMDllLoader;
iv_JVMDllLoader = NULL;
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_COULD_NOT_LOAD_JAVA_DLL,
UIMA_MSG_ID_EXC_COULD_NOT_LOAD_JAVA_DLL,
UIMA_MSG_ID_EXCON_PROCESSING_JAVA_TAE,
ErrorInfo::unrecoverable);
} else {
// get function pointers
iv_createJavaVMFunc = (TyCreateJavaVMFunc) iv_JVMDllLoader->getProcedure( "JNI_CreateJavaVM");
if ( iv_createJavaVMFunc == NULL ) {
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_COULD_NOT_LOAD_JAVA_DLL,
UIMA_MSG_ID_EXC_COULD_NOT_LOAD_JAVA_DLL,
UIMA_MSG_ID_EXCON_PROCESSING_JAVA_TAE,
ErrorInfo::unrecoverable);
}
iv_getCreatedJavaVMsFunc = (TyGetCreatedJavaVMsFunc) iv_JVMDllLoader->getProcedure("JNI_GetCreatedJavaVMs");
if ( iv_getCreatedJavaVMsFunc == NULL ) {
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_COULD_NOT_LOAD_JAVA_DLL,
UIMA_MSG_ID_EXC_COULD_NOT_LOAD_JAVA_DLL,
UIMA_MSG_ID_EXCON_PROCESSING_JAVA_TAE,
ErrorInfo::unrecoverable);
}
}
}
void JEDIIEngine::destroyJVMFunctions() {
if (iv_JVMDllLoader != NULL) {
assert( EXISTS(iv_JVMDllLoader) );
delete iv_JVMDllLoader;
iv_createJavaVMFunc = NULL;
iv_getCreatedJavaVMsFunc = NULL;
}
}
void JEDIIEngine::initializeJavaVM() {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
JavaVM* vms[1];
vms[0] = NULL;
jsize existingVMs = 0;
iv_createdVM = false;
UIMA_TPRINT("check if VM exists");
assert( EXISTS(iv_getCreatedJavaVMsFunc) );
jint existingVMsRes = (*iv_getCreatedJavaVMsFunc)(vms, 1, & existingVMs);
UIMA_TPRINT("JNI return code of getCreatedVMs: " << existingVMsRes);
if (existingVMsRes != JNI_OK) {
handleJNIError(existingVMsRes);
}
UIMA_TPRINT("existing VMs: " << existingVMs);
// if we don't already run within a Java context
if (existingVMs == 0) {
UIMA_TPRINT("new VM must be created");
iv_createdVM = true;
// get classpath from environment
util::EnvironmentVariableQueryOnly envVar("CLASSPATH");
char const * classpath = envVar.getValue();
char const * cpOption = "-Djava.class.path=";
char const * emptyString = "";
if (classpath == NULL) {
classpath = emptyString;
}
size_t cpBufLen = strlen(classpath) + strlen(cpOption) + 1;
auto_array<char> cpBuf( new char[cpBufLen] );
cpBuf[0] = 0;
strcat( strcat(cpBuf.get(), cpOption), classpath );
// create and initialize Java VM
char * optionStrings[] = {
cpBuf.get(),
"-Xmx256MB",
#ifndef NDEBUG
"-Xcheck:jni",
"-Xcheck:nabounds",
#endif
};
JavaVMInitArgs vmArgs;
vmArgs.version = USED_JAVA_VERSION;
JavaVMOption options[NUMBEROF(optionStrings)];
size_t i;
for (i=0; i<NUMBEROF(optionStrings); ++i) {
options[i].optionString = optionStrings[i];
}
vmArgs.nOptions = NUMBEROF(optionStrings);
vmArgs.options = options;
vmArgs.ignoreUnrecognized = JNI_FALSE;
UIMA_TPRINT("creating VM");
assert( iv_createJavaVMFunc != NULL);
jint vmCreationRes = (*iv_createJavaVMFunc)(& iv_vm, (void **)& iv_env, &vmArgs);
UIMA_TPRINT("VM created");
if (vmCreationRes != JNI_OK) {
clTrace.dump("Java VM could not be created, return code:", vmCreationRes);
iv_vm = NULL;
iv_env = NULL;
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_JAVA_EXCEPTION,
ErrorMessage(UIMA_MSG_ID_EXC_JAVA_VM_COULD_NOT_BE_CREATED, javaErrorToString(vmCreationRes)),
UIMA_MSG_ID_EXCON_PROCESSING_JAVA_TAE,
ErrorInfo::unrecoverable);
}
UIMA_TPRINT("VM created");
} else {
// re-use existing VM
UIMA_TPRINT("Using existing VM: " << vms[0]);
assert( existingVMsRes == JNI_OK );
assert( existingVMs == 1);
jint getenvRes = vms[0]->GetEnv((void**) & iv_env, USED_JAVA_VERSION);
handleJNIError(getenvRes);
assert( getenvRes == JNI_OK );
iv_vm = vms[0];
}
assert( EXISTS(iv_env) );
assert( EXISTS(iv_vm) );
}
TyErrorId JEDIIEngine::initializeImpl(AnalysisEngineDescription const & specifier) {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
UIMA_TPRINT("initializing JVM DLL");
initializeJVMFunctions();
UIMA_TPRINT("JVM DLL loaded");
assert( iv_createJavaVMFunc != NULL );
assert( iv_getCreatedJavaVMsFunc != NULL );
if (specifier.isPrimitive()) {
iv_isPrimitive = 1;
} else {
iv_isPrimitive = 2;
}
icu::UnicodeString config;
specifier.toXMLBuffer(config);
// ofstream ofs("jedii_tmp_specifier.xml"); ofs << config << endl; ofs.close();
UIMA_TPRINT("Initializing Java VM");
initializeJavaVM();
UIMA_TPRINT("VM initialized");
assert( EXISTS(iv_env) );
assert( EXISTS(iv_vm) );
TyErrorId err = UIMA_ERR_NONE;
UIMA_TPRINT("setup VM");
// create Java object and initialize method IDs
assert( EXISTS(iv_env) );
jclass clazz = iv_env->FindClass("org/apache/uima/uimacpp/CppUimajEngine");
checkForUnexpectedJNIException();
jmethodID constructor = iv_env->GetMethodID(clazz, "<init>", "()V");
checkForUnexpectedJNIException();
iv_initializeMethod = iv_env->GetMethodID(clazz, "initialize", "("
"Ljava/lang/String;" // config,
"Ljava/lang/String;" // datapath
"[I" // typeInheritance
"[I" // typePriorities
"[I" // featureDefs
"[I" // featureOffset
"[Ljava/lang/String;" // typeNames
"[Ljava/lang/String;" // featureNames
"[I" // stringSubTypes
"[Ljava/lang/String;" // stringSubTypeValues
"[I" // stringSubTypeValuePos
"[Ljava/lang/String;" // indexIDs
"[I" // indexKinds
"[I" // compStarts
"[I" // compDefs
")I");
checkForUnexpectedJNIException();
//check if UIMA Framework version is compatible
iv_getVersionMethod = iv_env->GetStaticMethodID(clazz, "getVersion", "()Ljava/lang/String;");
checkForUnexpectedJNIException();
jobject versionStringObj = iv_env->CallStaticObjectMethod(clazz, iv_getVersionMethod);
checkForUnexpectedJNIException();
jstring versionString = (jstring) versionStringObj;
const TCHAR ** compatibleVersions = gs_compatibleUIMAVersions;
if (versionString != NULL) {
cout << versionString << endl;
jboolean isCopy;
jchar const * jc = iv_env->GetStringChars(versionString, &isCopy);
checkForUnexpectedJNIException();
jsize js = iv_env->GetStringLength(versionString);
checkForUnexpectedJNIException();
icu::UnicodeString uVersion((UChar const *) jc, (size_t) js);
cout << uVersion << endl;
bool compatible = false;
for (int i=0; i < NUM_COMPATIBLE_UIMA_JAVA_VERSIONS; i++) {
if (uVersion.compare(compatibleVersions[i]) == 0) {
compatible=true;
}
}
if (!compatible) {
ErrorMessage msg = ErrorMessage(UIMA_MSG_ID_INCOMPATIBLE_UIMA_JAVA_VERSION);
msg.addParam(uVersion);
for (int i=0; i < NUM_COMPATIBLE_UIMA_JAVA_VERSIONS; i++) {
msg.addParam(compatibleVersions[i]);
}
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_JAVA_EXCEPTION,
msg,
UIMA_MSG_ID_INCOMPATIBLE_UIMA_JAVA_VERSION,
ErrorInfo::unrecoverable);
}
iv_env->ReleaseStringChars(versionString, jc);
checkForUnexpectedJNIException();
} else {
ErrorMessage msg = ErrorMessage(UIMA_MSG_ID_INCOMPATIBLE_UIMA_JAVA_VERSION);
msg.addParam("could not determine UIMA Java version");
UIMA_EXC_THROW_NEW(JavaException,
UIMA_ERR_JAVA_EXCEPTION,
msg,
UIMA_MSG_ID_INCOMPATIBLE_UIMA_JAVA_VERSION,
ErrorInfo::unrecoverable);
}
iv_processMethod = iv_env->GetMethodID(clazz, "process", "("
"Ljava/lang/String;" // doc
"[I" // heap
"[I" // fsIndex
"[Ljava/lang/String;" // stringTable
"[I" // resultSpecTypes
"[I" // resultSpecFeatures
"I" // sofanum
"[B" // byte heap
"[S" // short heap
"[J" // long heap
")I");
checkForUnexpectedJNIException();
iv_getByteHeapMethod = iv_env->GetMethodID(clazz, "getByteHeap", "()[B");
checkForUnexpectedJNIException();
iv_getShortHeapMethod = iv_env->GetMethodID(clazz, "getShortHeap", "()[S");
checkForUnexpectedJNIException();
iv_getLongHeapMethod = iv_env->GetMethodID(clazz, "getLongHeap", "()[J");
checkForUnexpectedJNIException();
iv_destroyMethod = iv_env->GetMethodID(clazz, "destroy", "()I");
checkForUnexpectedJNIException();
iv_getLastExceptionStringMethod = iv_env->GetMethodID(clazz, "getLastExceptionString", "()Ljava/lang/String;");
checkForUnexpectedJNIException();
iv_getHeapMethod = iv_env->GetMethodID(clazz, "getHeap", "()[I");
checkForUnexpectedJNIException();
iv_getIndexedFSsMethod = iv_env->GetMethodID(clazz, "getIndexedFSs", "()[I");
checkForUnexpectedJNIException();
iv_getStringTableMethod = iv_env->GetMethodID(clazz, "getStringTable", "()[Ljava/lang/String;");
checkForUnexpectedJNIException();
iv_batchProcessCompleteMethod = iv_env->GetMethodID(clazz, "batchProcessComplete", "()I");
checkForUnexpectedJNIException();
iv_collectionProcessCompleteMethod = iv_env->GetMethodID(clazz, "collectionProcessComplete", "()I");
checkForUnexpectedJNIException();
iv_obj = iv_env->NewObject(clazz, constructor);
checkForUnexpectedJNIException();
iv_obj = iv_env->NewGlobalRef(iv_obj);
checkForUnexpectedJNIException();
UIMA_TPRINT("setup VM complete");
// serialize type system and pass it to the initialize method
CASSerializer serializer(true);
SerializedCAS serializedCAS;
serializer.serializeDefinitions( *iv_casDefinition, serializedCAS);
UIMA_TPRINT("definitions serialized");
{
jint pushFrameResult = iv_env->PushLocalFrame(serializedCAS.getNumberOfJavaObjectsToBeCreatedDefinitions() );
checkForUnexpectedJNIException();
handleEngineProxyError(pushFrameResult);
checkForUnexpectedJNIException();
// prepare arguments for initialize()
jintArray typeInheritance = createJIntArray(serializedCAS.getTypeInheritanceTable() );
jintArray typePriorities = createJIntArray(serializedCAS.getTypePriorityTable());
jintArray featureDefs = createJIntArray(serializedCAS.getFeatureDefinitionTable());
jintArray featureOffset = createJIntArray(serializedCAS.getFeatureOffsetTable());
jobjectArray typeNames = createJStringArray(serializedCAS.getTypeSymbolTable());
jobjectArray featureNames = createJStringArray(serializedCAS.getFeatureSymbolTable());
jintArray subStringTypes = createJIntArray(serializedCAS.getStringSubTypes());
jobjectArray subStringTypeValues = createJStringArray(serializedCAS.getStringSubTypeValues());
jintArray subStringTypeValuePos = createJIntArray(serializedCAS.getStringSubTypeValuePos());
jintArray indexKinds = createJIntArray(serializedCAS.getIndexKindTable());
jintArray compStarts = createJIntArray(serializedCAS.getComparatorStartTable());
jintArray compDefs = createJIntArray(serializedCAS.getComparatorDefinitionTable());
jobjectArray indexIDs = createJStringArray(serializedCAS.getIndexIDTable());
jstring conf = iv_env->NewString((jchar const *)config.getBuffer(), config.length());
checkForUnexpectedJNIException();
icu::UnicodeString dataPathUS(uima::ResourceManager::getInstance().getLocationData().getAsCString() );
jstring dataPath = iv_env->NewString((jchar const *)dataPathUS.getBuffer(), dataPathUS.length() );
checkForUnexpectedJNIException();
UIMA_TPRINT("Java args created");
// call initialize on org.apache.uima.uimacpp.CppUimajEngine
jint initResult = iv_env->CallIntMethod(iv_obj, iv_initializeMethod,
conf,
dataPath,
typeInheritance,
typePriorities,
featureDefs,
featureOffset,
typeNames,
featureNames,
subStringTypes,
subStringTypeValues,
subStringTypeValuePos,
indexIDs,
indexKinds,
compStarts,
compDefs);
checkForUnexpectedJNIException();
handleEngineProxyError(initResult);
UIMA_TPRINT("Java initalize called");
iv_env->PopLocalFrame(NULL);
checkForUnexpectedJNIException();
}
UIMA_TPRINT("result spec initialized");
return err;
}
TyErrorId JEDIIEngine::reinitTypeSystemImpl() {
return initializeImpl(getAnnotatorContext().getTaeSpecifier());
}
TyErrorId JEDIIEngine::processImpl(CAS & cas, ResultSpecification const & resultSpec) {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
UIMA_TPRINT("serializing data");
TyErrorId err = UIMA_ERR_NONE;
// serialize CAS and pass it to process method
CASSerializer serializer(true);
SerializedCAS serializedInCAS;
// serializer.serializeData( TCAS::promoteCAS(cas), serializedInCAS);
serializer.serializeData(cas, serializedInCAS);
UIMA_TPRINT("data serialized");
{
jint pushFrameRes = iv_env->PushLocalFrame( serializedInCAS.getNumberOfJavaObjectsToBeCreatedData());
checkForUnexpectedJNIException();
handleJNIError(pushFrameRes);
// prepare arguments
jstring doc = createJString( serializedInCAS.getDocument() );
jintArray inHeap = createJIntArray(serializedInCAS.getFSHeapArray() );
jintArray inIndexedFSs = createJIntArray(serializedInCAS.getIndexedFSs() );
jobjectArray inStrings = createJStringArray(serializedInCAS.getStringSymbolTable());
jbyteArray inByteHeap = createJByteArray(serializedInCAS.getByteHeapArray() );
jshortArray inShortHeap = createJShortArray(serializedInCAS.getShortHeapArray() );
jlongArray inLongHeap = createJLongArray(serializedInCAS.getLongHeapArray() );
vector<internal::SerializedCAS::TyNum> resultSpecTypes;
vector<internal::SerializedCAS::TyNum> resultSpecFeatures;
CASSerializer::serializeResultSpec(resultSpec, resultSpecTypes, resultSpecFeatures);
jintArray inRSTypes = createJIntArray(resultSpecTypes);
jintArray inRSFeatures = createJIntArray(resultSpecFeatures);
UIMA_TPRINT("args to Java initialize created");
int sofaNum=0;
if (cas.isView() ) {
sofaNum = cas.getSofaNum();
}
// call process()
jint result = iv_env->CallIntMethod(iv_obj, iv_processMethod,
doc,
inHeap,
inIndexedFSs,
inStrings,
inRSTypes,
inRSFeatures,
sofaNum,
inByteHeap,
inShortHeap,
inLongHeap);
checkForUnexpectedJNIException();
handleEngineProxyError(result);
UIMA_TPRINT("Java initialize done");
iv_env->PopLocalFrame(NULL);
checkForUnexpectedJNIException();
}
if (err != UIMA_ERR_NONE) {
return err;
}
UIMA_TPRINT("De-serializing per-document data");
SerializedCAS serializedOutCAS;
// get serialized CAS from Java object
jintArray outHeapArray = (jintArray) iv_env->CallObjectMethod(iv_obj, iv_getHeapMethod);
checkForUnexpectedJNIException();
createIntVector(outHeapArray, serializedOutCAS.iv_vecFSHeapArray );
jbyteArray byteHeapArray = (jbyteArray) iv_env->CallObjectMethod(iv_obj, iv_getByteHeapMethod);
checkForUnexpectedJNIException();
createByteVector(byteHeapArray, serializedOutCAS.iv_vecByteHeapArray );
jintArray outIndexedFSsArray = (jintArray) iv_env->CallObjectMethod(iv_obj, iv_getIndexedFSsMethod);
checkForUnexpectedJNIException();
createIntVector(outIndexedFSsArray, serializedOutCAS.iv_vecIndexedFSs);
jobjectArray outStringsArray = (jobjectArray) iv_env->CallObjectMethod(iv_obj, iv_getStringTableMethod);
checkForUnexpectedJNIException();
createStringVector(outStringsArray, serializedOutCAS.iv_vecStringSymbolTable, iv_stringPool);
serializedOutCAS.iv_ulstrDocument = serializedInCAS.getDocument();
UIMA_TPRINT("De-serialized data received from Java");
CASDeserializer deSerializer;
// deSerializer.deserializeData(serializedOutCAS, TCAS::promoteCAS( cas ));
deSerializer.deserializeData(serializedOutCAS, cas);
UIMA_TPRINT("data deserialized");
return err;
}
TyErrorId JEDIIEngine::reconfigureImpl() {
util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
// no reconfiguration of the JEDII engine possible yet
return UIMA_ERR_NONE;
}
bool JEDIIEngine::hasNextImpl() {
util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
//TODO:
return false;
}
CAS & JEDIIEngine::nextImpl() {
util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
//TODO::return iv_pAnnotator->next();
UIMA_EXC_THROW_NEW(ExcInvalidRequest,
UIMA_ERR_NOT_YET_IMPLEMENTED,
UIMA_MSG_ID_EXC_INVALID_CALL_TO_NEXT,
UIMA_MSG_ID_EXC_INVALID_CALL_TO_NEXT,
ErrorInfo::unrecoverable);
}
int JEDIIEngine::getCasInstancesRequiredImpl() {
util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
//TODO::return iv_pAnnotator->next();
return 0;
}
void JEDIIEngine::destroyJavaVM() {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
if (iv_createdVM) {
iv_createdVM = false;
jint destroyRC = iv_vm->DestroyJavaVM();
checkForUnexpectedJNIException();
if (destroyRC != JNI_OK) {
char c[2056];
icu::UnicodeString us = javaErrorToString(destroyRC);
us.extract(0, us.length(), c);
clTrace.dump("Java VM could not be destroyed, return code: ", c);
#ifndef NDEBUG
cerr << __FILE__ << __LINE__ << ": Java VM could not be destroyed (return code: " << javaErrorToString(destroyRC) << ")" << endl;
#endif
}
}
iv_vm = NULL;
iv_env = NULL;
}
TyErrorId JEDIIEngine::destroyImpl() {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
if (iv_vm != NULL) {
assert( iv_env != NULL );
if (iv_obj != NULL) {
jint destroyResult = iv_env->CallIntMethod(iv_obj, iv_destroyMethod);
checkForUnexpectedJNIException();
handleEngineProxyError(destroyResult);
iv_env->DeleteGlobalRef(iv_obj);
checkForUnexpectedJNIException();
iv_obj = NULL;
}
destroyJavaVM();
assert( iv_vm == NULL );
assert( iv_env == NULL );
destroyJVMFunctions();
}
return UIMA_ERR_NONE;
}
TyErrorId JEDIIEngine::batchProcessCompleteImpl() {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
TyErrorId err = UIMA_ERR_NONE;
jint result = iv_env->CallIntMethod(iv_obj, iv_batchProcessCompleteMethod);
checkForUnexpectedJNIException();
handleEngineProxyError(result);
return err;
}
TyErrorId JEDIIEngine::collectionProcessCompleteImpl() {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
TyErrorId err = UIMA_ERR_NONE;
jint result = iv_env->CallIntMethod(iv_obj, iv_collectionProcessCompleteMethod);
checkForUnexpectedJNIException();
handleEngineProxyError(result);
return err;
}
}
}