📄 jniutil.cpp
字号:
g_finalizedObjects.push_back(cl);
}
/**
* 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 *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)
{
JNICriticalSection cs(*g_logMutex);
g_logStream << "NullPointerException thrown" << std::endl;
}
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 + -