JniUtil.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/farrago/JniUtil.cpp#35 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2005-2009 SQLstream, Inc.
00006 // Copyright (C) 2005-2009 LucidEra, Inc.
00007 // Portions Copyright (C) 1999-2009 John V. Sichi
00008 //
00009 // This program is free software; you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by the Free
00011 // Software Foundation; either version 2 of the License, or (at your option)
00012 // any later version approved by The Eigenbase Project.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/farrago/JniUtil.h"
00026 #include "fennel/farrago/JavaExcn.h"
00027 #include "fennel/common/FennelResource.h"
00028 #include "fennel/common/ConfigMap.h"
00029 #include "fennel/common/Backtrace.h"
00030 #include "fennel/tuple/StoredTypeDescriptor.h"
00031 
00032 #ifdef __MSVC__
00033 #include <process.h>
00034 #endif
00035 
00036 #ifndef __MSVC__
00037 #include <signal.h>
00038 #endif
00039 
00040 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/farrago/JniUtil.cpp#35 $");
00041 
00042 ParamName JniUtilParams::paramJniHandleTraceFile = "jniHandleTraceFile";
00043 
00044 JavaVM *JniUtil::pVm = NULL;
00045 jmethodID JniUtil::methGetClassName = 0;
00046 jmethodID JniUtil::methGetInterfaces = 0;
00047 jmethodID JniUtil::methGetModifiers = 0;
00048 jclass JniUtil::classModifier = 0;
00049 jmethodID JniUtil::methIsPublic = 0;
00050 jmethodID JniUtil::methHasNext = 0;
00051 jmethodID JniUtil::methNext = 0;
00052 jmethodID JniUtil::methIterator = 0;
00053 jmethodID JniUtil::methGetJavaStreamHandle = 0;
00054 jmethodID JniUtil::methGetIndexRoot = 0;
00055 jmethodID JniUtil::methToString = 0;
00056 jclass JniUtil::classRhBase64;
00057 jmethodID JniUtil::methRandomUUID;
00058 jclass JniUtil::classUUID;
00059 jmethodID JniUtil::methFarragoTransformInit = 0;
00060 jmethodID JniUtil::methFarragoTransformExecute = 0;
00061 jmethodID JniUtil::methFarragoTransformSetInputFetchTimeout = 0;
00062 jmethodID JniUtil::methFarragoTransformRestart = 0;
00063 jclass JniUtil::classFarragoTransformInputBinding = 0;
00064 jmethodID JniUtil::methFarragoTransformInputBindingCons = 0;
00065 jmethodID JniUtil::methFarragoRuntimeContextStatementClassForName = 0;
00066 jmethodID JniUtil::methFarragoRuntimeContextFindFarragoTransform = 0;
00067 jclass JniUtil::classLong;
00068 jclass JniUtil::classInteger;
00069 jclass JniUtil::classShort;
00070 jclass JniUtil::classDouble;
00071 jclass JniUtil::classFloat;
00072 jclass JniUtil::classBoolean;
00073 jmethodID JniUtil::methLongValueOf = 0;
00074 jmethodID JniUtil::methIntegerValueOf = 0;
00075 jmethodID JniUtil::methShortValueOf = 0;
00076 jmethodID JniUtil::methDoubleValueOf = 0;
00077 jmethodID JniUtil::methFloatValueOf = 0;
00078 jmethodID JniUtil::methBooleanValueOf = 0;
00079 jmethodID JniUtil::methLongValue = 0;
00080 jmethodID JniUtil::methIntValue = 0;
00081 jmethodID JniUtil::methShortValue = 0;
00082 jmethodID JniUtil::methDoubleValue = 0;
00083 jmethodID JniUtil::methFloatValue = 0;
00084 jmethodID JniUtil::methBooleanValue = 0;
00085 jmethodID JniUtil::methBase64Decode;
00086 jmethodID JniUtil::methUtilGetStackTrace;
00087 jclass JniUtil::classUtil;
00088 
00089 AtomicCounter JniUtil::handleCount;
00090 
00091 bool JniUtil::traceHandleCountEnabled = false;
00092 bool JniUtil::closeHandleCountTraceOnZero = false;
00093 std::ofstream JniUtil::handleCountTraceStream;
00094 
00095 JavaThreadTracker JniUtil::threadTracker;
00096 
00097 
00098 #ifndef __MSVC__
00099 static void debugger_signalHandler(int signum)
00100 {
00101     // do nothing
00102 }
00103 #endif
00104 
00105 JniUtilParams::JniUtilParams()
00106 {
00107     jniHandleTraceFile = "";
00108 }
00109 
00110 void JniUtilParams::readConfig(ConfigMap const &configMap)
00111 {
00112     jniHandleTraceFile = configMap.getStringParam(paramJniHandleTraceFile);
00113 }
00114 
00115 void JniUtil::initDebug(char const *envVarName)
00116 {
00117     char *pDebug = getenv(envVarName);
00118     if (pDebug && (atoi(pDebug) >= 1)) {
00119         char pidstr[32];
00120         snprintf(pidstr, 32, "%d", getpid());
00121         std::cout << "Waiting for debugger; pid=" << pidstr << std::endl;
00122         std::cout.flush();
00123 #ifdef __MSVC__
00124         // A "cont" in gdb will wake this sleep up immediately, which
00125         // is disturbing but useful.
00126         _sleep(600000);
00127 #else
00128         // On older versions of Linux, a "cont" in gdb will wake this
00129         // sleep up immediately, which is disturbing but useful.
00130         // On newer versions, the continue command resumes
00131         // the sleep().  So, if $envVarName > 1, wait for SIGHUP.
00132         // Use the "signal 1" command to wake the pause up.
00133         if (atoi(pDebug) == 1) {
00134             sleep(60000);
00135         } else {
00136             struct sigaction act;
00137             struct sigaction oldact;
00138 
00139             act.sa_handler = debugger_signalHandler;
00140             sigemptyset(&act.sa_mask);
00141             act.sa_flags = 0;
00142 
00143             if (!sigaction(SIGHUP, &act, &oldact)) {
00144                 // Signal handler installed properly.  Wait for signal.
00145                 pause();
00146 
00147                 // Restore the old signal handler.
00148                 sigaction(SIGHUP, &oldact, NULL);
00149             } else {
00150                 // Fall back on sleeping.
00151                 sleep(60000);
00152             }
00153         }
00154 #endif
00155     }
00156 }
00157 
00158 void JniUtil::configure(const JniUtilParams &params)
00159 {
00160     // Check if the stream is already open.  During unit tests Fennel is
00161     // sometimes stopped and restarted in a single process.  Flag an error
00162     // if this happens, it means the previous shutdown failed.
00163     if (handleCountTraceStream.is_open()) {
00164         assert(false);
00165 
00166         // Non-debug builds: clean up
00167         handleCountTraceStream
00168             << "ERROR: trace stream already open" << std::endl;
00169         handleCountTraceStream.flush();
00170         handleCountTraceStream.close();
00171         traceHandleCountEnabled = false;
00172         closeHandleCountTraceOnZero = false;
00173     }
00174 
00175     if (params.jniHandleTraceFile.length() > 0) {
00176         handleCountTraceStream.open(
00177             params.jniHandleTraceFile.c_str(), std::ios::app);
00178 
00179         handleCountTraceStream
00180             << "# Fennel JNI Handle Trace (see //open/util/bin/checkJniHandleTrace.pl)"
00181             << std::endl;
00182 
00183         assert(handleCountTraceStream.good());
00184 
00185         traceHandleCountEnabled = true;
00186         closeHandleCountTraceOnZero = false;
00187     }
00188 }
00189 
00190 void JniUtil::shutdown()
00191 {
00192     // JavaTraceTarget decrements after DbHandle.  Set a flag to close the
00193     // trace stream when the counter hits zero.
00194     if (traceHandleCountEnabled) {
00195         closeHandleCountTraceOnZero = true;
00196     }
00197 }
00198 
00199 
00200 jint JniUtil::init(JavaVM *pVmInit)
00201 {
00202     // Install handler to print backtrace on fatal error.  Note that
00203     // we pass false to suppress handling of SIGSEGV, because Java
00204     // raises this spuriously.  Instead, if a real SIGSEGV occurs
00205     // in native code, Java will abort, raising SIGABRT from the same
00206     // stack frame, so we'll catch that and backtrace it instead.
00207     AutoBacktrace::install(false);
00208     pVm = pVmInit;
00209     JniEnvAutoRef pEnv;
00210     jclass classClass = pEnv->FindClass("java/lang/Class");
00211     jclass classObject = pEnv->FindClass("java/lang/Object");
00212     jclass classCollection = pEnv->FindClass("java/util/Collection");
00213     jclass classIterator = pEnv->FindClass("java/util/Iterator");
00214 
00215     // Make sure this jclass is a global ref or the JVM might move it on us.
00216     // This is only required for classes on which we need to invoke
00217     // static methods.
00218     classRhBase64 = pEnv->FindClass("org/eigenbase/util/RhBase64");
00219     classRhBase64 = (jclass) pEnv->NewGlobalRef(classRhBase64);
00220     classUUID = pEnv->FindClass("java/util/UUID");
00221     classUUID = (jclass) pEnv->NewGlobalRef(classUUID);
00222 
00223     jclass classFennelJavaStreamMap = pEnv->FindClass(
00224         "net/sf/farrago/fennel/FennelJavaStreamMap");
00225     jclass classFarragoTransform = pEnv->FindClass(
00226         "net/sf/farrago/runtime/FarragoTransform");
00227 
00228     // Make sure this jclass is a global ref of the JVM might move it on us.
00229     jclass tempInputBinding =
00230         pEnv->FindClass(
00231             "net/sf/farrago/runtime/FarragoTransform$InputBinding");
00232     classFarragoTransformInputBinding =
00233         (jclass)pEnv->NewGlobalRef(tempInputBinding);
00234 
00235     jclass classFarragoRuntimeContext = pEnv->FindClass(
00236         "net/sf/farrago/runtime/FarragoRuntimeContext");
00237     methGetClassName = pEnv->GetMethodID(
00238         classClass,"getName","()Ljava/lang/String;");
00239     methGetInterfaces = pEnv->GetMethodID(
00240         classClass,"getInterfaces","()[Ljava/lang/Class;");
00241     methGetModifiers = pEnv->GetMethodID(
00242         classClass,"getModifiers","()I");
00243 
00244     jclass tempClassModifier = pEnv->FindClass("java/lang/reflect/Modifier");
00245     classModifier = (jclass)pEnv->NewGlobalRef(tempClassModifier);
00246     methIsPublic = pEnv->GetStaticMethodID(classModifier, "isPublic", "(I)Z");
00247 
00248     methIterator = pEnv->GetMethodID(
00249         classCollection,"iterator","()Ljava/util/Iterator;");
00250     methHasNext = pEnv->GetMethodID(
00251         classIterator,"hasNext","()Z");
00252     methNext = pEnv->GetMethodID(
00253         classIterator,"next","()Ljava/lang/Object;");
00254     methGetJavaStreamHandle = pEnv->GetMethodID(
00255         classFennelJavaStreamMap,"getJavaStreamHandle",
00256         "(I)J");
00257     methGetIndexRoot = pEnv->GetMethodID(
00258         classFennelJavaStreamMap,"getIndexRoot",
00259         "(J)J");
00260     methToString = pEnv->GetMethodID(
00261         classObject,"toString","()Ljava/lang/String;");
00262 
00263     jclass tempClassLong = pEnv->FindClass("java/lang/Long");
00264     classLong = (jclass)pEnv->NewGlobalRef(tempClassLong);
00265     methLongValueOf =
00266         pEnv->GetStaticMethodID(classLong, "valueOf", "(J)Ljava/lang/Long;");
00267     methLongValue = pEnv->GetMethodID(classLong, "longValue", "()J");
00268 
00269     jclass tempClassInteger = pEnv->FindClass("java/lang/Integer");
00270     classInteger = (jclass)pEnv->NewGlobalRef(tempClassInteger);
00271     methIntegerValueOf =
00272         pEnv->GetStaticMethodID(
00273             classInteger, "valueOf", "(I)Ljava/lang/Integer;");
00274     methIntValue = pEnv->GetMethodID(classInteger, "intValue", "()I");
00275 
00276     jclass tempClassShort = pEnv->FindClass("java/lang/Short");
00277     classShort = (jclass)pEnv->NewGlobalRef(tempClassShort);
00278     methShortValueOf =
00279         pEnv->GetStaticMethodID(classShort, "valueOf", "(S)Ljava/lang/Short;");
00280     methShortValue = pEnv->GetMethodID(classShort, "shortValue", "()S");
00281 
00282     jclass tempClassDouble = pEnv->FindClass("java/lang/Double");
00283     classDouble = (jclass)pEnv->NewGlobalRef(tempClassDouble);
00284     methDoubleValueOf =
00285         pEnv->GetStaticMethodID(
00286             classDouble, "valueOf", "(D)Ljava/lang/Double;");
00287     methDoubleValue = pEnv->GetMethodID(classDouble, "doubleValue", "()D");
00288 
00289     jclass tempClassFloat = pEnv->FindClass("java/lang/Float");
00290     classFloat = (jclass)pEnv->NewGlobalRef(tempClassFloat);
00291     methFloatValueOf =
00292         pEnv->GetStaticMethodID(classFloat, "valueOf", "(F)Ljava/lang/Float;");
00293     methFloatValue = pEnv->GetMethodID(classFloat, "floatValue", "()F");
00294 
00295     jclass tempClassBoolean = pEnv->FindClass("java/lang/Boolean");
00296     classBoolean = (jclass)pEnv->NewGlobalRef(tempClassBoolean);
00297     methBooleanValueOf =
00298         pEnv->GetStaticMethodID(
00299             classBoolean, "valueOf", "(Z)Ljava/lang/Boolean;");
00300     methBooleanValue = pEnv->GetMethodID(classBoolean, "booleanValue", "()Z");
00301 
00302     methBase64Decode = pEnv->GetStaticMethodID(
00303         classRhBase64,"decode","(Ljava/lang/String;)[B");
00304     methRandomUUID = pEnv->GetStaticMethodID(
00305         classUUID,"randomUUID","()Ljava/util/UUID;");
00306 
00307     methFarragoTransformInit = pEnv->GetMethodID(
00308         classFarragoTransform, "init",
00309         "(Lnet/sf/farrago/runtime/FarragoRuntimeContext;Ljava/lang/String;[Lnet/sf/farrago/runtime/FarragoTransform$InputBinding;)V");
00310     methFarragoTransformExecute = pEnv->GetMethodID(
00311         classFarragoTransform, "execute", "(Ljava/nio/ByteBuffer;J)I");
00312     methFarragoTransformRestart = pEnv->GetMethodID(
00313         classFarragoTransform, "restart", "()V");
00314     methFarragoTransformSetInputFetchTimeout = pEnv->GetMethodID(
00315         classFarragoTransform, "setInputFetchTimeout", "(J)V");
00316     methFarragoTransformInputBindingCons =
00317         pEnv->GetMethodID(
00318             classFarragoTransformInputBinding, "<init>",
00319             "(Ljava/lang/String;I)V");
00320     methFarragoRuntimeContextStatementClassForName =
00321         pEnv->GetMethodID(
00322             classFarragoRuntimeContext,
00323             "statementClassForName",
00324             "(Ljava/lang/String;)Ljava/lang/Class;");
00325     methFarragoRuntimeContextFindFarragoTransform =
00326         pEnv->GetMethodID(
00327             classFarragoRuntimeContext,
00328             "findFarragoTransform",
00329             "(Ljava/lang/String;)Lnet/sf/farrago/runtime/FarragoTransform;");
00330 
00331     jclass tempClassUtil = pEnv->FindClass("org/eigenbase/util/Util");
00332     classUtil = (jclass) pEnv->NewGlobalRef(tempClassUtil);
00333     methUtilGetStackTrace = pEnv->GetStaticMethodID(
00334         classUtil, "getStackTrace",
00335         "(Ljava/lang/Throwable;)Ljava/lang/String;");
00336 
00337     return jniVersion;
00338 }
00339 
00340 JNIEnv *JniUtil::getAttachedJavaEnv(bool &needDetach)
00341 {
00342     void *pEnv = NULL;
00343     jint rc = pVm->GetEnv(&pEnv,jniVersion);
00344     if (rc == JNI_OK) {
00345         // previously attached, so it would be wrong to detach in destructor
00346         needDetach = false;
00347         return static_cast<JNIEnv *>(pEnv);
00348     }
00349     needDetach = true;
00350     rc = pVm->AttachCurrentThread(&pEnv,NULL);
00351     assert(rc == 0);
00352     assert(pEnv);
00353     return static_cast<JNIEnv *>(pEnv);
00354 }
00355 
00356 void JniUtil::detachJavaEnv()
00357 {
00358     jint rc = pVm->DetachCurrentThread();
00359     assert(rc == 0);
00360 }
00361 
00362 std::string JniUtil::getClassName(jclass jClass)
00363 {
00364     JniEnvAutoRef pEnv;
00365     jstring jString = reinterpret_cast<jstring>(
00366         pEnv->CallObjectMethod(jClass,methGetClassName));
00367     assert(jString);
00368     return toStdString(pEnv,jString);
00369 }
00370 
00371 std::string JniUtil::getFirstPublicInterfaceName(jclass jClass)
00372 {
00373     JniEnvAutoRef pEnv;
00374 
00375     jobjectArray ifaces =
00376         reinterpret_cast<jobjectArray>(
00377             pEnv->CallObjectMethod(jClass, methGetInterfaces));
00378     assert(ifaces);
00379 
00380     for (jsize i = 0, len = pEnv->GetArrayLength(ifaces); i < len; i++) {
00381         jclass iface =
00382             reinterpret_cast<jclass>(
00383                 pEnv->GetObjectArrayElement(ifaces, i));
00384         assert(iface);
00385 
00386         jint modifiers =
00387             pEnv->CallIntMethod(iface, methGetModifiers);
00388 
00389         jboolean isPublic =
00390             pEnv->CallStaticBooleanMethod(
00391                 classModifier, methIsPublic, modifiers);
00392 
00393         if (isPublic) {
00394             return getClassName(iface);
00395         }
00396     }
00397 
00398     return std::string("(none)");
00399 }
00400 
00401 std::string JniUtil::toStdString(JniEnvRef pEnv,jstring jString)
00402 {
00403     const char *pChars = pEnv->GetStringUTFChars(jString,NULL);
00404     assert(pChars);
00405     std::string str(pChars,pEnv->GetStringUTFLength(jString));
00406     pEnv->ReleaseStringUTFChars(jString,pChars);
00407     return str;
00408 }
00409 
00410 jstring JniUtil::toString(JniEnvRef pEnv,jobject jObject)
00411 {
00412     return reinterpret_cast<jstring>(
00413         pEnv->CallObjectMethod(jObject,methToString));
00414 }
00415 
00416 uint JniUtil::lookUpEnum(std::string *pSymbols,std::string const &symbol)
00417 {
00418     for (uint i = 0; ; ++i) {
00419         assert(pSymbols[i].size());
00420         if (pSymbols[i] == symbol) {
00421             return i;
00422         }
00423     }
00424 }
00425 
00426 jobject JniUtil::getIter(JniEnvRef pEnv,jobject jCollection)
00427 {
00428     return pEnv->CallObjectMethod(jCollection,methIterator);
00429 }
00430 
00431 jobject JniUtil::getNextFromIter(JniEnvRef pEnv,jobject jIter)
00432 {
00433     if (!pEnv->CallBooleanMethod(jIter,methHasNext)) {
00434         return NULL;
00435     }
00436     return pEnv->CallObjectMethod(jIter,methNext);
00437 }
00438 
00439 void JniUtil::incrementHandleCount(const char *pType, const void *pHandle)
00440 {
00441     ++handleCount;
00442 
00443     traceHandleCount("INC", pType, pHandle);
00444 }
00445 
00446 void JniUtil::decrementHandleCount(const char *pType, const void *pHandle)
00447 {
00448     --handleCount;
00449 
00450     assert(handleCount >= 0);
00451 
00452     traceHandleCount("DEC", pType, pHandle);
00453 }
00454 
00455 void JniUtil::traceHandleCount(
00456     const char *pAction, const char *pType, const void *pHandle)
00457 {
00458     if (traceHandleCountEnabled) {
00459         handleCountTraceStream
00460             << pAction << " " << pType << ": " << pHandle << std::endl;
00461 
00462         if (handleCount == 0 && closeHandleCountTraceOnZero &&
00463             strcmp(pAction, "DEC") == 0) {
00464             traceHandleCountEnabled = false;
00465             closeHandleCountTraceOnZero = false;
00466 
00467             handleCountTraceStream.flush();
00468             handleCountTraceStream.close();
00469         }
00470     }
00471 }
00472 
00473 std::string JniUtil::getXmi(const TupleDescriptor &tupleDescriptor)
00474 {
00475     std::ostringstream oss;
00476     oss << "<XMI xmi.version = '1.2' "
00477         << "xmlns:FEMFennel = 'org.omg.xmi.namespace.FEMFennel'>" << std::endl;
00478     oss << "<XMI.content>" << std::endl;
00479     oss << "<FEMFennel:TupleDescriptor>" << std::endl;
00480     for (uint i = 0; i < tupleDescriptor.size(); ++i) {
00481         TupleAttributeDescriptor const &attrDescriptor =
00482             tupleDescriptor[i];
00483         oss << "<FEMFennel:TupleDescriptor.AttrDescriptor>";
00484         oss << "<FEMFennel:TupleAttrDescriptor ";
00485         oss << "typeOrdinal='";
00486         oss << attrDescriptor.pTypeDescriptor->getOrdinal();
00487         oss << "' ";
00488         oss << "isNullable='";
00489         oss << (attrDescriptor.isNullable ? "true" : "false");
00490         oss << "' ";
00491         oss << "byteLength='";
00492         oss << attrDescriptor.cbStorage;
00493         oss << "' ";
00494         oss << "/>" << std::endl;
00495         oss << "</FEMFennel:TupleDescriptor.AttrDescriptor>";
00496     }
00497     oss << "</FEMFennel:TupleDescriptor>" << std::endl;
00498     oss << "</XMI.content>" << std::endl;
00499     oss << "</XMI>" << std::endl;
00500     std::string s = oss.str();
00501     return s;
00502 }
00503 
00504 ThreadTracker &JniUtil::getThreadTracker()
00505 {
00506     return threadTracker;
00507 }
00508 
00509 void JniExceptionChecker::checkExceptions()
00510 {
00511     jthrowable excn = pEnv->ExceptionOccurred();
00512     if (excn) {
00513         pEnv->ExceptionClear();
00514         throw JavaExcn(excn);
00515     }
00516 }
00517 
00518 JniExceptionChecker::~JniExceptionChecker()
00519 {
00520     checkExceptions();
00521 }
00522 
00523 JniEnvAutoRef::JniEnvAutoRef()
00524     : JniEnvRef(JniUtil::getAttachedJavaEnv(needDetach))
00525 {
00526 }
00527 
00528 JniEnvAutoRef::~JniEnvAutoRef()
00529 {
00530     if (needDetach) {
00531         JniUtil::detachJavaEnv();
00532     }
00533 }
00534 
00535 void JniEnvAutoRef::suppressDetach()
00536 {
00537     needDetach = false;
00538 }
00539 
00540 void JniEnvRef::handleExcn(std::exception &ex)
00541 {
00542     JavaExcn *pJavaExcn = dynamic_cast<JavaExcn *>(&ex);
00543     if (pJavaExcn) {
00544         pEnv->Throw(pJavaExcn->getJavaException());
00545         return;
00546     }
00547     std::string what;
00548     FennelExcn *pFennelExcn = dynamic_cast<FennelExcn *>(&ex);
00549     if (pFennelExcn) {
00550         what = pFennelExcn->getMessage();
00551     } else {
00552         std::bad_alloc *pBadAllocExcn =
00553             dynamic_cast<std::bad_alloc *>(&ex);
00554         if (pBadAllocExcn) {
00555             // Convert bad_alloc's terrible error mesage into something fit for
00556             // human consumption.
00557             what = FennelResource::instance().internalError("malloc failed");
00558         } else {
00559             what = FennelResource::instance().internalError(ex.what());
00560         }
00561     }
00562     // TODO:  need special-case handling for out-of-memory here
00563     jclass classSQLException = pEnv->FindClass("java/sql/SQLException");
00564     jstring jMessage = pEnv->NewStringUTF(what.c_str());
00565     jmethodID constructor = pEnv->GetMethodID(
00566         classSQLException,"<init>","(Ljava/lang/String;)V");
00567     jthrowable t = (jthrowable)
00568         pEnv->NewObject(classSQLException,constructor,jMessage);
00569     pEnv->Throw(t);
00570 }
00571 
00572 void JniPseudoUuidGenerator::generateUuid(PseudoUuid &pseudoUuid)
00573 {
00574     JniEnvAutoRef pEnv;
00575     jobject jUuid = pEnv->CallStaticObjectMethod(
00576         JniUtil::classUUID,
00577         JniUtil::methRandomUUID);
00578     jstring jsUuid = JniUtil::toString(pEnv, jUuid);
00579     std::string sUuid = JniUtil::toStdString(pEnv, jsUuid);
00580     pseudoUuid.parse(sUuid);
00581 }
00582 
00583 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/farrago/JniUtil.cpp#35 $");
00584 
00585 // End JniUtil.cpp

Generated on Mon Jun 22 04:00:19 2009 for Fennel by  doxygen 1.5.1