void JNIUtil::throwNativeException(const char *className, const char *msg, const char *source, int aprErr) { JNIEnv *env = getEnv(); jclass clazz = env->FindClass(className); // Create a local frame for our references env->PushLocalFrame(LOCAL_FRAME_SIZE); if (JNIUtil::isJavaExceptionThrown()) return; if (getLogLevel() >= exceptionLog) { JNICriticalSection cs(*g_logMutex); g_logStream << "Subversion JavaHL exception thrown, message:<"; g_logStream << msg << ">"; if (source) g_logStream << " source:<" << source << ">"; if (aprErr != -1) g_logStream << " apr-err:<" << aprErr << ">"; g_logStream << std::endl; } if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jstring jmessage = makeJString(msg); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jstring jsource = makeJString(source); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jmethodID mid = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;I)V"); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jobject nativeException = env->NewObject(clazz, mid, jmessage, jsource, static_cast<jint>(aprErr)); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); env->Throw(static_cast<jthrowable>(env->PopLocalFrame(nativeException))); }
/** * Callback called for a single status item. */ void ChangelistCallback::doChangelist(const char *path, const char *changelist, apr_pool_t *pool) { JNIEnv *env = JNIUtil::getEnv(); // Create a local frame for our references env->PushLocalFrame(LOCAL_FRAME_SIZE); if (JNIUtil::isJavaExceptionThrown()) return; static jmethodID mid = 0; // the method id will not change during // the time this library is loaded, so // it can be cached. if (mid == 0) { jclass clazz = env->FindClass(JAVA_PACKAGE"/callback/ChangelistCallback"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); mid = env->GetMethodID(clazz, "doChangelist", "(Ljava/lang/String;Ljava/lang/String;)V"); if (JNIUtil::isJavaExceptionThrown() || mid == 0) POP_AND_RETURN_NOTHING(); } jstring jChangelist = JNIUtil::makeJString(changelist); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jstring jPath = JNIUtil::makeJString(path); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); env->CallVoidMethod(m_callback, mid, jPath, jChangelist); env->PopLocalFrame(NULL); }
void OperationContext::progress(apr_off_t progressVal, apr_off_t total, void *baton, apr_pool_t *pool) { jobject jctx = (jobject) baton; if (!jctx) return; JNIEnv *env = JNIUtil::getEnv(); // Create a local frame for our references env->PushLocalFrame(LOCAL_FRAME_SIZE); if (JNIUtil::isJavaExceptionThrown()) return; static jmethodID mid = 0; if (mid == 0) { jclass clazz = env->GetObjectClass(jctx); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); mid = env->GetMethodID(clazz, "onProgress", "(" JAVAHL_ARG("/ProgressEvent;") ")V"); if (JNIUtil::isJavaExceptionThrown() || mid == 0) POP_AND_RETURN_NOTHING(); } static jmethodID midCT = 0; jclass clazz = env->FindClass(JAVAHL_CLASS("/ProgressEvent")); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); if (midCT == 0) { midCT = env->GetMethodID(clazz, "<init>", "(JJ)V"); if (JNIUtil::isJavaExceptionThrown() || midCT == 0) POP_AND_RETURN_NOTHING(); } // Call the Java method. jobject jevent = env->NewObject(clazz, midCT, (jlong) progressVal, (jlong) total); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); env->CallVoidMethod(jctx, mid, jevent); POP_AND_RETURN_NOTHING(); }
void JNIUtil::wrappedHandleSVNError(svn_error_t *err) { std::string msg; assembleErrorMessage(svn_error_purge_tracing(err), 0, APR_SUCCESS, msg); const char *source = NULL; #ifdef SVN_DEBUG #ifndef SVN_ERR__TRACING if (err->file) { std::ostringstream buf; buf << err->file; if (err->line > 0) buf << ':' << err->line; source = buf.str().c_str(); } #endif #endif // Much of the following is stolen from throwNativeException(). As much as // we'd like to call that function, we need to do some manual stack // unrolling, so it isn't feasible. JNIEnv *env = getEnv(); // Create a local frame for our references env->PushLocalFrame(LOCAL_FRAME_SIZE); if (JNIUtil::isJavaExceptionThrown()) return; jclass clazz = env->FindClass(JAVA_PACKAGE "/ClientException"); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); if (getLogLevel() >= exceptionLog) { JNICriticalSection cs(*g_logMutex); g_logStream << "Subversion JavaHL exception thrown, message:<"; g_logStream << msg << ">"; if (source) g_logStream << " source:<" << source << ">"; if (err->apr_err != -1) g_logStream << " apr-err:<" << err->apr_err << ">"; g_logStream << std::endl; } if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jstring jmessage = makeJString(msg.c_str()); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jstring jsource = makeJString(source); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jmethodID mid = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;I)V"); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); jobject nativeException = env->NewObject(clazz, mid, jmessage, jsource, static_cast<jint>(err->apr_err)); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); #ifdef SVN_ERR__TRACING // Add all the C error stack trace information to the Java Exception // Get the standard stack trace, and vectorize it using the Array class. static jmethodID mid_gst = 0; if (mid_gst == 0) { mid_gst = env->GetMethodID(clazz, "getStackTrace", "()[Ljava/lang/StackTraceElement;"); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); } Array stackTraceArray((jobjectArray) env->CallObjectMethod(nativeException, mid_gst)); std::vector<jobject> oldStackTrace = stackTraceArray.vector(); // Build the new stack trace elements from the chained errors. std::vector<jobject> newStackTrace; putErrorsInTrace(err, newStackTrace); // Join the new elements with the old ones for (std::vector<jobject>::const_iterator it = oldStackTrace.begin(); it < oldStackTrace.end(); ++it) { newStackTrace.push_back(*it); } jclass stClazz = env->FindClass("java/lang/StackTraceElement"); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); const jsize stSize = static_cast<jsize>(newStackTrace.size()); if (stSize != newStackTrace.size()) { env->ThrowNew(env->FindClass("java.lang.ArithmeticException"), "Overflow converting C size_t to JNI jsize"); POP_AND_RETURN_NOTHING(); } jobjectArray jStackTrace = env->NewObjectArray(stSize, stClazz, NULL); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); int i = 0; for (std::vector<jobject>::const_iterator it = newStackTrace.begin(); it < newStackTrace.end(); ++it) { env->SetObjectArrayElement(jStackTrace, i, *it); ++i; } // And put the entire trace back into the exception static jmethodID mid_sst = 0; if (mid_sst == 0) { mid_sst = env->GetMethodID(clazz, "setStackTrace", "([Ljava/lang/StackTraceElement;)V"); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); } env->CallVoidMethod(nativeException, mid_sst, jStackTrace); if (isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); #endif env->Throw(static_cast<jthrowable>(env->PopLocalFrame(nativeException))); }
Revision::Revision(jobject jthis, bool headIfUnspecified, bool oneIfUnspecified) { if (jthis == NULL) { m_revision.kind = svn_opt_revision_unspecified; m_revision.value.number = 0; } else { JNIEnv *env = JNIUtil::getEnv(); // Create a local frame for our references env->PushLocalFrame(LOCAL_FRAME_SIZE); if (JNIUtil::isJavaExceptionThrown()) return; static jfieldID fid = 0; if (fid == 0) { jclass clazz = env->FindClass(JAVA_PACKAGE"/types/Revision"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); fid = env->GetFieldID(clazz, "revKind", "L"JAVA_PACKAGE"/types/Revision$Kind;"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); } jobject jKind = env->GetObjectField(jthis, fid); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); m_revision.value.number = 0; m_revision.kind = EnumMapper::toRevisionKind(jKind); switch(m_revision.kind) { case svn_opt_revision_number: { static jfieldID fidNum = 0; if (fidNum == 0) { jclass clazz = env->FindClass(JAVA_PACKAGE"/types/Revision$Number"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); fidNum = env->GetFieldID(clazz, "revNumber", "J"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); } jlong jNumber = env->GetLongField(jthis, fidNum); m_revision.value.number = (svn_revnum_t) jNumber; } break; case svn_opt_revision_date: { static jfieldID fidDate = 0; if (fidDate == 0) { jclass clazz = env->FindClass(JAVA_PACKAGE"/types/Revision$DateSpec"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); fidDate = env->GetFieldID(clazz, "revDate", "Ljava/util/Date;"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); } jobject jDate = env->GetObjectField(jthis, fidDate); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); static jmethodID mid = 0; if (mid == 0) { jclass clazz = env->FindClass("java/util/Date"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); mid = env->GetMethodID(clazz, "getTime", "()J"); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); } jlong jMillSec = env->CallLongMethod(jDate, mid); if (JNIUtil::isJavaExceptionThrown()) POP_AND_RETURN_NOTHING(); m_revision.value.date = jMillSec * 1000; } break; default: /* None of the other revision kinds need special handling. */ break; } env->PopLocalFrame(NULL); } if (headIfUnspecified && m_revision.kind == svn_opt_revision_unspecified) m_revision.kind = svn_opt_revision_head; else if (oneIfUnspecified && m_revision.kind == svn_opt_revision_unspecified) { m_revision.kind = svn_opt_revision_number; m_revision.value.number = 1; } }