| /** |
| * @copyright |
| * ==================================================================== |
| * 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. |
| * ==================================================================== |
| * @endcopyright |
| * |
| * @file JNIUtil.h |
| * @brief Interface of the class JNIUtil |
| */ |
| |
| #ifndef JNIUTIL_H |
| #define JNIUTIL_H |
| |
| #include <list> |
| #include <vector> |
| #include "Pool.h" |
| struct apr_pool_t; |
| class JNIMutex; |
| class SVNBase; |
| #include <jni.h> |
| #include <fstream> |
| #include <apr_time.h> |
| #include <string> |
| #include <vector> |
| |
| struct svn_error_t; |
| struct svn_string_t; |
| |
| #include "svn_error.h" |
| |
| |
| /** |
| * The name of the package in which the JavaHL classes are defined. |
| */ |
| #define JAVAHL_PACKAGE "org/apache/subversion/javahl" |
| |
| /** |
| * Construct a JavaHL class name for JNIEnv::FindClass. |
| */ |
| #define JAVAHL_CLASS(name) JAVAHL_PACKAGE name |
| |
| /** |
| * Construct a JavaHL class parameter name for JNIEnv::GetMethodID & co. |
| */ |
| #define JAVAHL_ARG(name) "L" JAVAHL_PACKAGE name |
| |
| |
| /** |
| * Class to hold a number of JNI related utility methods. No Objects |
| * of this class are ever created. |
| */ |
| class JNIUtil |
| { |
| public: |
| static svn_error_t *preprocessPath(const char *&path, apr_pool_t *pool); |
| |
| /** |
| * Throw the Java NativeException instance named by |
| * exceptionClassName. A NativeException sub-class must supply a |
| * 3-arg constructor identical to that of NativeException. @a |
| * source is any file name and line number information. |
| */ |
| static void throwNativeException(const char *exceptionClassName, |
| const char *msg, |
| const char *source = NULL, |
| int aprErr = -1); |
| |
| static void throwNullPointerException(const char *message); |
| static jbyteArray makeJByteArray(const void *data, int length); |
| static jbyteArray makeJByteArray(const svn_string_t *str); |
| static jobject createDate(apr_time_t time); |
| static apr_time_t getDate(jobject jdate); |
| static void logMessage(const char *message); |
| static int getLogLevel(); |
| static void initLogFile(int level, jstring path); |
| static jstring makeJString(const char *txt); |
| static JNIEnv *getEnv(); |
| |
| /** |
| * @return Whether any Throwable has been raised. |
| */ |
| static bool isExceptionThrown() { return isJavaExceptionThrown(); } |
| static bool isJavaExceptionThrown() |
| { |
| return getEnv()->ExceptionCheck(); |
| } |
| |
| static svn_error_t *wrapJavaException(); |
| static jthrowable unwrapJavaException(const svn_error_t *err); |
| |
| static void handleAPRError(int error, const char *op); |
| |
| /** |
| * Put @a object in the list of finalized objects queued up to be |
| * deleted (by another thread) during the next operation. |
| * |
| * @param object The C++ peer of the finalized (Java) object. |
| * @since 1.4.0 |
| */ |
| static void enqueueForDeletion(SVNBase *object); |
| |
| /** |
| * @deprecated Use the more appropriately named |
| * enqueueForDeletion() instead. |
| */ |
| static void putFinalizedClient(SVNBase *cl); |
| |
| /** |
| * Convert any exception that may have been thrown into a textual |
| * representation. Return @c NULL if no exception has |
| * occurred. Useful for converting Java @c Exceptions into @c |
| * svn_error_t's. |
| */ |
| static const char *thrownExceptionToCString(SVN::Pool &in_pool); |
| |
| /** |
| * Check if a Java exception was thrown and convert it to a |
| * Subversion error, using @a errorcode as the generic error code. |
| */ |
| static svn_error_t* checkJavaException(apr_status_t errorcode); |
| |
| /** |
| * Create a Java exception corresponding to err, and run |
| * svn_error_clear() on err. |
| */ |
| static jthrowable createClientException(svn_error_t *err, |
| jthrowable jcause = NULL); |
| |
| /** |
| * Throw a Java exception corresponding to err, and run |
| * svn_error_clear() on err. |
| */ |
| static void handleSVNError(svn_error_t *err, jthrowable jcause = NULL); |
| |
| static std::string makeSVNErrorMessage(svn_error_t *err, |
| jstring *jerror_message, |
| jobject *jmessage_stack); |
| |
| /** |
| * Create and throw a java.lang.Throwable instance. |
| * |
| * @param name The class name (in path form, with slashes in lieu |
| * of dots) of the Throwable to create and raise. |
| * @param message The message text of the Throwable. |
| */ |
| static void raiseThrowable(const char *name, const char *message); |
| |
| /** |
| * Creates and throws a JNIError. |
| * |
| * @param message The message text of the JNIError. |
| */ |
| static void throwError(const char *message) |
| { |
| raiseThrowable(JAVAHL_CLASS("/JNIError"), message); |
| } |
| |
| static apr_pool_t *getPool(); |
| static bool JNIInit(JNIEnv *env); |
| static bool initializeJNIRuntime(); |
| enum { noLog, errorLog, exceptionLog, entryLog } LogLevel; |
| |
| /** |
| * Mutex that secures the global configuration object. |
| */ |
| static JNIMutex *g_configMutex; |
| |
| private: |
| friend bool initialize_jni_util(JNIEnv *env); |
| static bool JNIGlobalInit(JNIEnv *env); |
| |
| static jthrowable wrappedCreateClientException(svn_error_t *err, |
| jthrowable jcause); |
| static void putErrorsInTrace(svn_error_t *err, |
| std::vector<jobject> &stackTrace); |
| |
| /** |
| * The log level of this module. |
| */ |
| static int g_logLevel; |
| |
| /** |
| * Global master pool. All other pool are subpools of this pool. |
| */ |
| static apr_pool_t *g_pool; |
| |
| /** |
| * List of objects finalized, where the C++ peer has not yet be |
| * deleted. |
| */ |
| static std::list<SVNBase*> g_finalizedObjects; |
| |
| /** |
| * Mutex to secure the g_finalizedObjects list. |
| */ |
| static JNIMutex *g_finalizedObjectsMutex; |
| |
| /** |
| * Mutex to secure the access to the log file. |
| */ |
| static JNIMutex *g_logMutex; |
| |
| /** |
| * Flag, that an exception occurred during our initialization. |
| */ |
| static bool g_initException; |
| |
| /** |
| * The stream to write log messages to. |
| */ |
| static std::ofstream g_logStream; |
| }; |
| |
| /** |
| * A statement macro used for checking NULL pointers, in the style of |
| * SVN_ERR(). |
| * |
| * Evaluate @a expr. If it equals NULL, throw an NullPointerException with |
| * the value @a str, and return the @a ret_val. Otherwise, continue. |
| * |
| * Note that if the enclosing function returns <tt>void</tt>, @a ret_val may |
| * be blank. |
| */ |
| |
| #define SVN_JNI_NULL_PTR_EX(expr, str, ret_val) \ |
| if ((expr) == NULL) { \ |
| JNIUtil::throwNullPointerException(str); \ |
| return ret_val; \ |
| } |
| |
| /** |
| * A statement macro used for checking for errors, in the style of |
| * SVN_ERR(). |
| * |
| * Evalute @a expr. If it yields an error, handle the JNI error, and |
| * return @a ret_val. Otherwise, continue. |
| * |
| * Note that if the enclosing function returns <tt>void</tt>, @a ret_val may |
| * be blank. |
| */ |
| |
| #define SVN_JNI_ERR(expr, ret_val) \ |
| do { \ |
| svn_error_t *svn_jni_err__temp = (expr); \ |
| if (svn_jni_err__temp != SVN_NO_ERROR) { \ |
| JNIUtil::handleSVNError(svn_jni_err__temp); \ |
| return ret_val; \ |
| } \ |
| } while (0) |
| |
| /** |
| * The initial capacity of a create local reference frame. |
| */ |
| #define LOCAL_FRAME_SIZE 16 |
| |
| /** |
| * A statement macro use to pop the reference frame and return NULL |
| */ |
| #define POP_AND_RETURN(ret_val) \ |
| do \ |
| { \ |
| env->PopLocalFrame(NULL); \ |
| return ret_val; \ |
| } \ |
| while (0) |
| |
| /** |
| * A statement macro use to pop the reference frame and return |
| */ |
| #define POP_AND_RETURN_NOTHING() \ |
| do \ |
| { \ |
| env->PopLocalFrame(NULL); \ |
| return; \ |
| } \ |
| while (0) |
| |
| #define POP_AND_RETURN_EXCEPTION_AS_SVNERROR() \ |
| do \ |
| { \ |
| svn_error_t *svn__err_for_exception = JNIUtil::wrapJavaException(); \ |
| \ |
| env->PopLocalFrame(NULL); \ |
| return svn__err_for_exception; \ |
| } \ |
| while (0) |
| |
| |
| /** |
| * A useful macro. |
| */ |
| #define POP_AND_RETURN_NULL POP_AND_RETURN(NULL) |
| |
| #define CPPADDR_NULL_PTR(expr, ret_val) \ |
| do { \ |
| if ((expr) == NULL) { \ |
| JNIUtil::throwError(_("bad C++ this")); \ |
| return ret_val; \ |
| } \ |
| } while (0) |
| |
| #define SVN_JNI_CATCH(statement, errorcode) \ |
| do { \ |
| do { statement; } while(0); \ |
| SVN_ERR(JNIUtil::checkJavaException((errorcode))); \ |
| } while(0) |
| |
| #define SVN_JNI_CATCH_VOID(statement) \ |
| do { \ |
| do { statement; } while(0); \ |
| if (JNIUtil::getEnv()->ExceptionCheck()) { \ |
| JNIUtil::getEnv()->ExceptionClear(); \ |
| return; \ |
| } \ |
| } while(0) |
| |
| /** |
| * If there's an exception pending, temporarily stash it away, then |
| * re-throw again in destructor. The goal is to allow some Java calls |
| * to be made despite a pending exception. For example, doing some |
| * necessary cleanup. |
| */ |
| class StashException |
| { |
| public: |
| /* |
| * Works like stashException(). |
| */ |
| StashException(JNIEnv* env); |
| |
| /** |
| * If there's an exception stashed, re-throws it. |
| */ |
| ~StashException(); |
| |
| /** |
| * Check for a pending exception. |
| * If present, stash it away until this class's destructor. |
| * If another exception is already stashed, forget the _new_ one. The |
| * reason behind it is that usually the first exception is the most |
| * informative. |
| */ |
| void stashException(); |
| |
| private: |
| JNIEnv* m_env; |
| jthrowable m_stashed; |
| }; |
| |
| #endif // JNIUTIL_H |