| /** \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; |
| } |
| |
| |
| |
| } |
| } |
| |
| |
| |
| |