📄 jniutil.cpp
字号:
}void JNIUtil::enqueueForDeletion(SVNBase *object){ JNICriticalSection cs(*g_finalizedObjectsMutex); if (!isExceptionThrown()) { g_finalizedObjects.push_back(object); }}/** * Handle an apr error (those are not expected) by throwing an error * @param error the apr error number * @param op the apr function returning the error */void JNIUtil::handleAPRError(int error, const char *op){ char *buffer = getFormatBuffer(); if(buffer == NULL) { return; } apr_snprintf(buffer, formatBufferSize, _("an error occurred in function %s with return value %d"), op, error); throwError(buffer);}/** * return is an exception has been detected * @return a exception has been detected */bool JNIUtil::isExceptionThrown(){ if(g_inInit) // during init -> look in the global member { return g_initException; } // look in the thread local storage JNIThreadData *data = JNIThreadData::getThreadData(); return data == NULL || data->m_exceptionThrown;}/** * store the JNI environment for this request in the thread local storage * @param env the JNI environment */void JNIUtil::setEnv(JNIEnv *env){ JNIThreadData::pushNewThreadData(); JNIThreadData *data = JNIThreadData::getThreadData(); data->m_env = env; data->m_exceptionThrown = false;}/** * Return the JNI environment to use * @return the JNI environment */JNIEnv * JNIUtil::getEnv(){ // during init -> look into the global variable if(g_inInit) { return g_initEnv; } // look in the thread local storage JNIThreadData *data = JNIThreadData::getThreadData(); return data->m_env;}/** * check in a java exception has been thrown * @return is a java exception has been thrown */bool JNIUtil::isJavaExceptionThrown(){ JNIEnv *env = getEnv(); if(env->ExceptionCheck()) { // retrieving the exception removes it // so we rethrow it here jthrowable exp = env->ExceptionOccurred(); env->ExceptionDescribe(); env->Throw(exp); env->DeleteLocalRef(exp); setExceptionThrown(); return true; } return false;}/** * create a java string from a native UTF-8 string * @param txt native UTF-8 string * @return the java string. It is a local reference, which should be deleted * as soon a possible */ jstring JNIUtil::makeJString(const char *txt){ if(txt == NULL) // NULL string can be converted to a null java string { return NULL; } JNIEnv *env = getEnv(); jstring js = env->NewStringUTF(txt); return js;}/** * set the flag, that an exception has been thrown */void JNIUtil::setExceptionThrown(){ // during init -> store in global variable if(g_inInit) { g_initException = true; } // store in thread local storage JNIThreadData *data = JNIThreadData::getThreadData(); data->m_exceptionThrown = true;}/** * initialite the log file * @param level the log level * @param the name of the log file */void JNIUtil::initLogFile(int level, jstring path){ // lock this operation JNICriticalSection cs(*g_logMutex); if(g_logLevel > noLog) // if the log file has been opened { g_logStream.close(); } // remember the log level g_logLevel = level; JNIStringHolder myPath(path); if(g_logLevel > noLog) // if a new log file is needed { // open it g_logStream.open(myPath, std::ios::app); }}/** * Returns a buffer to format error messages * @return a buffer for formating error messages */char * JNIUtil::getFormatBuffer(){ if(g_inInit) // during init -> use the global buffer { return g_initFormatBuffer; } // use the buffer in the thread local storage JNIThreadData *data = JNIThreadData::getThreadData(); if(data == NULL) // if that does not exists -> use the global buffer { return g_initFormatBuffer; } return data->m_formatBuffer;}/** * Returns the current log level * @return the log level */int JNIUtil::getLogLevel(){ return g_logLevel;}/** * write a message to the log file if needed * @param the log message */void JNIUtil::logMessage(const char *message){ // lock the log file JNICriticalSection cs(*g_logMutex); g_logStream << message << std::endl;}/** * create a java.util.Date object from an apr time * @param time the apr time * @return the java.util.Date. This is a local reference. Delete as soon as * possible */jobject JNIUtil::createDate(apr_time_t time){ jlong javatime = time /1000; JNIEnv *env = getEnv(); jclass clazz = env->FindClass("java/util/Date"); if(isJavaExceptionThrown()) { return NULL; } static jmethodID mid = 0; if(mid == 0) { mid = env->GetMethodID(clazz, "<init>", "(J)V"); if(isJavaExceptionThrown()) { return NULL; } } jobject ret = env->NewObject(clazz, mid, javatime); if(isJavaExceptionThrown()) { return NULL; } env->DeleteLocalRef(clazz); if(isJavaExceptionThrown()) { return NULL; } return ret;}/** * Return the request pool. The request pool will be destroyed after each * request (call) * @return the pool to be used for this request */Pool * JNIUtil::getRequestPool(){ return JNIThreadData::getThreadData()->m_requestPool;}/** * Set the request pool in thread local storage * @param pool the request pool */void JNIUtil::setRequestPool(Pool *pool){ JNIThreadData::getThreadData()->m_requestPool = pool;}/** * create a java byte array from an array of characters. * @param data the character array * @param length the number of characters in the array */jbyteArray JNIUtil::makeJByteArray(const signed char *data, int length){ if(data == NULL || length == 0) // a NULL or empty will create no // java array { return NULL; } JNIEnv *env = getEnv(); // allocate the java array jbyteArray ret = env->NewByteArray(length); if(isJavaExceptionThrown()) { return NULL; } // access the bytes jbyte *retdata = env->GetByteArrayElements(ret, NULL); if(isJavaExceptionThrown()) { return NULL; } // copy the bytes memcpy(retdata, data, length); // release the bytes env->ReleaseByteArrayElements(ret, retdata, 0); if(isJavaExceptionThrown()) { return NULL; } return ret;}/** * build the error message from the svn error into buffer. This method calls * itselft recursivly for all the chained errors * * @param err the subversion error * @param depth the depth of the call, used for formating * @param parent_apr_err the apr of the previous level, used for formating * @param buffer the buffer where the formated error message will * be stored */void JNIUtil::assembleErrorMessage(svn_error_t *err, int depth, apr_status_t parent_apr_err, std::string &buffer){ // buffer for a single error message char errbuf[256]; /* Pretty-print the error */ /* Note: we can also log errors here someday. */ /* When we're recursing, don't repeat the top-level message if its the same as before. */ if (depth == 0 || err->apr_err != parent_apr_err) { /* Is this a Subversion-specific error code? */ if ((err->apr_err > APR_OS_START_USEERR) && (err->apr_err <= APR_OS_START_CANONERR)) buffer.append(svn_strerror (err->apr_err, errbuf, sizeof (errbuf))); /* Otherwise, this must be an APR error code. */ else buffer.append(apr_strerror (err->apr_err, errbuf, sizeof (errbuf))); buffer.append("\n"); } if (err->message) buffer.append(_("svn: ")).append(err->message).append("\n"); if (err->child) assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);}/** * Throw a java NullPointerException. Used when input parameters which should * not be null are that. * * @param message the name of the parameter that is null */void JNIUtil::throwNullPointerException(const char *message){ if (getLogLevel() >= errorLog) { logMessage("NullPointerException thrown"); } JNIEnv *env = getEnv(); jclass clazz = env->FindClass("java/lang/NullPointerException"); if(isJavaExceptionThrown()) { return; } env->ThrowNew(clazz, message); setExceptionThrown(); env->DeleteLocalRef(clazz);}svn_error_t *JNIUtil::preprocessPath(const char *&path, apr_pool_t * pool){ /* URLs and wc-paths get treated differently. */ if (svn_path_is_url (path)) { /* No need to canonicalize a URL's case or path separators. */ /* Convert to URI. */ path = svn_path_uri_from_iri (path, pool); /* Auto-escape some ASCII characters. */ path = svn_path_uri_autoescape (path, pool); /* The above doesn't guarantee a valid URI. */ if (! svn_path_is_uri_safe (path)) return svn_error_createf (SVN_ERR_BAD_URL, 0, _("URL '%s' is not properly URI-encoded"), path); /* Verify that no backpaths are present in the URL. */ if (svn_path_is_backpath_present (path)) return svn_error_createf (SVN_ERR_BAD_URL, 0, _("URL '%s' contains a '..' element"), path); /* strip any trailing '/' */ path = svn_path_canonicalize (path, pool); } else /* not a url, so treat as a path */ { const char *apr_target; char *truenamed_target; /* APR-encoded */ apr_status_t apr_err; /* canonicalize case, and change all separators to '/'. */ SVN_ERR (svn_path_cstring_from_utf8 (&apr_target, path, pool)); apr_err = apr_filepath_merge (&truenamed_target, "", apr_target, APR_FILEPATH_TRUENAME, pool); if (!apr_err) /* We have a canonicalized APR-encoded target now. */ apr_target = truenamed_target; else if (APR_STATUS_IS_ENOENT (apr_err)) /* It's okay for the file to not exist, that just means we have to accept the case given to the client. We'll use the original APR-encoded target. */ ; else return svn_error_createf (apr_err, NULL, _("Error resolving case of '%s'"), svn_path_local_style (path, pool)); /* convert back to UTF-8. */ SVN_ERR (svn_path_cstring_to_utf8 (&path, apr_target, pool)); path = svn_path_canonicalize (path, pool); } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -