summaryrefslogtreecommitdiff
path: root/share/swig/3.0.12/java/director.swg
diff options
context:
space:
mode:
Diffstat (limited to 'share/swig/3.0.12/java/director.swg')
-rw-r--r--share/swig/3.0.12/java/director.swg413
1 files changed, 413 insertions, 0 deletions
diff --git a/share/swig/3.0.12/java/director.swg b/share/swig/3.0.12/java/director.swg
new file mode 100644
index 0000000..355e62d
--- /dev/null
+++ b/share/swig/3.0.12/java/director.swg
@@ -0,0 +1,413 @@
+/* -----------------------------------------------------------------------------
+ * director.swg
+ *
+ * This file contains support for director classes so that Java proxy
+ * methods can be called from C++.
+ * ----------------------------------------------------------------------------- */
+
+#if defined(DEBUG_DIRECTOR_OWNED) || defined(DEBUG_DIRECTOR_EXCEPTION)
+#include <iostream>
+#endif
+
+#include <exception>
+
+namespace Swig {
+
+ /* Java object wrapper */
+ class JObjectWrapper {
+ public:
+ JObjectWrapper() : jthis_(NULL), weak_global_(true) {
+ }
+
+ ~JObjectWrapper() {
+ jthis_ = NULL;
+ weak_global_ = true;
+ }
+
+ bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) {
+ if (!jthis_) {
+ weak_global_ = weak_global || !mem_own; // hold as weak global if explicitly requested or not owned
+ if (jobj)
+ jthis_ = weak_global_ ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj);
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl;
+#endif
+ return true;
+ } else {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl;
+#endif
+ return false;
+ }
+ }
+
+ jobject get(JNIEnv *jenv) const {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::get(";
+ if (jthis_)
+ std::cout << jthis_;
+ else
+ std::cout << "null";
+ std::cout << ") -> return new local ref" << std::endl;
+#endif
+ return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_);
+ }
+
+ void release(JNIEnv *jenv) {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "weak global ref" : "global ref") << std::endl;
+#endif
+ if (jthis_) {
+ if (weak_global_) {
+ if (jenv->IsSameObject(jthis_, NULL) == JNI_FALSE)
+ jenv->DeleteWeakGlobalRef((jweak)jthis_);
+ } else
+ jenv->DeleteGlobalRef(jthis_);
+ }
+
+ jthis_ = NULL;
+ weak_global_ = true;
+ }
+
+ /* Only call peek if you know what you are doing wrt to weak/global references */
+ jobject peek() {
+ return jthis_;
+ }
+
+ /* Java proxy releases ownership of C++ object, C++ object is now
+ responsible for destruction (creates NewGlobalRef to pin Java proxy) */
+ void java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
+ if (take_or_release) { /* Java takes ownership of C++ object's lifetime. */
+ if (!weak_global_) {
+ jenv->DeleteGlobalRef(jthis_);
+ jthis_ = jenv->NewWeakGlobalRef(jself);
+ weak_global_ = true;
+ }
+ } else {
+ /* Java releases ownership of C++ object's lifetime */
+ if (weak_global_) {
+ jenv->DeleteWeakGlobalRef((jweak)jthis_);
+ jthis_ = jenv->NewGlobalRef(jself);
+ weak_global_ = false;
+ }
+ }
+ }
+
+ private:
+ /* pointer to Java object */
+ jobject jthis_;
+ /* Local or global reference flag */
+ bool weak_global_;
+ };
+
+ /* Local JNI reference deleter */
+ class LocalRefGuard {
+ JNIEnv *jenv_;
+ jobject jobj_;
+
+ // non-copyable
+ LocalRefGuard(const LocalRefGuard &);
+ LocalRefGuard &operator=(const LocalRefGuard &);
+ public:
+ LocalRefGuard(JNIEnv *jenv, jobject jobj): jenv_(jenv), jobj_(jobj) {}
+ ~LocalRefGuard() {
+ if (jobj_)
+ jenv_->DeleteLocalRef(jobj_);
+ }
+ };
+
+ /* director base class */
+ class Director {
+ /* pointer to Java virtual machine */
+ JavaVM *swig_jvm_;
+
+ protected:
+#if defined (_MSC_VER) && (_MSC_VER<1300)
+ class JNIEnvWrapper;
+ friend class JNIEnvWrapper;
+#endif
+ /* Utility class for managing the JNI environment */
+ class JNIEnvWrapper {
+ const Director *director_;
+ JNIEnv *jenv_;
+ int env_status;
+ public:
+ JNIEnvWrapper(const Director *director) : director_(director), jenv_(0), env_status(0) {
+#if defined(__ANDROID__)
+ JNIEnv **jenv = &jenv_;
+#else
+ void **jenv = (void **)&jenv_;
+#endif
+ env_status = director_->swig_jvm_->GetEnv((void **)&jenv_, JNI_VERSION_1_2);
+#if defined(SWIG_JAVA_ATTACH_CURRENT_THREAD_AS_DAEMON)
+ // Attach a daemon thread to the JVM. Useful when the JVM should not wait for
+ // the thread to exit upon shutdown. Only for jdk-1.4 and later.
+ director_->swig_jvm_->AttachCurrentThreadAsDaemon(jenv, NULL);
+#else
+ director_->swig_jvm_->AttachCurrentThread(jenv, NULL);
+#endif
+ }
+ ~JNIEnvWrapper() {
+#if !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD)
+ // Some JVMs, eg jdk-1.4.2 and lower on Solaris have a bug and crash with the DetachCurrentThread call.
+ // However, without this call, the JVM hangs on exit when the thread was not created by the JVM and creates a memory leak.
+ if (env_status == JNI_EDETACHED)
+ director_->swig_jvm_->DetachCurrentThread();
+#endif
+ }
+ JNIEnv *getJNIEnv() const {
+ return jenv_;
+ }
+ };
+
+ /* Java object wrapper */
+ JObjectWrapper swig_self_;
+
+ /* Disconnect director from Java object */
+ void swig_disconnect_director_self(const char *disconn_method) {
+ JNIEnvWrapper jnienv(this) ;
+ JNIEnv *jenv = jnienv.getJNIEnv() ;
+ jobject jobj = swig_self_.get(jenv);
+ LocalRefGuard ref_deleter(jenv, jobj);
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl;
+#endif
+ if (jobj && jenv->IsSameObject(jobj, NULL) == JNI_FALSE) {
+ jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V");
+ if (disconn_meth) {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "Swig::Director::disconnect_director_self upcall to " << disconn_method << std::endl;
+#endif
+ jenv->CallVoidMethod(jobj, disconn_meth);
+ }
+ }
+ }
+
+ public:
+ Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) NULL), swig_self_() {
+ /* Acquire the Java VM pointer */
+ jenv->GetJavaVM(&swig_jvm_);
+ }
+
+ virtual ~Director() {
+ JNIEnvWrapper jnienv(this) ;
+ JNIEnv *jenv = jnienv.getJNIEnv() ;
+ swig_self_.release(jenv);
+ }
+
+ bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) {
+ return swig_self_.set(jenv, jself, mem_own, weak_global);
+ }
+
+ jobject swig_get_self(JNIEnv *jenv) const {
+ return swig_self_.get(jenv);
+ }
+
+ // Change C++ object's ownership, relative to Java
+ void swig_java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
+ swig_self_.java_change_ownership(jenv, jself, take_or_release);
+ }
+ };
+
+ // Zero initialized bool array
+ template<size_t N> class BoolArray {
+ bool array_[N];
+ public:
+ BoolArray() {
+ memset(array_, 0, sizeof(array_));
+ }
+ bool& operator[](size_t n) {
+ return array_[n];
+ }
+ bool operator[](size_t n) const {
+ return array_[n];
+ }
+ };
+
+ // Utility classes and functions for exception handling.
+
+ // Simple holder for a Java string during exception handling, providing access to a c-style string
+ class JavaString {
+ public:
+ JavaString(JNIEnv *jenv, jstring jstr) : jenv_(jenv), jstr_(jstr), cstr_(0) {
+ if (jenv_ && jstr_)
+ cstr_ = (const char *) jenv_->GetStringUTFChars(jstr_, NULL);
+ }
+
+ ~JavaString() {
+ if (jenv_ && jstr_ && cstr_)
+ jenv_->ReleaseStringUTFChars(jstr_, cstr_);
+ }
+
+ const char *c_str(const char *null_string = "null JavaString") const {
+ return cstr_ ? cstr_ : null_string;
+ }
+
+ private:
+ // non-copyable
+ JavaString(const JavaString &);
+ JavaString &operator=(const JavaString &);
+
+ JNIEnv *jenv_;
+ jstring jstr_;
+ const char *cstr_;
+ };
+
+ // Helper class to extract the exception message from a Java throwable
+ class JavaExceptionMessage {
+ public:
+ JavaExceptionMessage(JNIEnv *jenv, jthrowable throwable) : message_(jenv, exceptionMessageFromThrowable(jenv, throwable)) {
+ }
+
+ const char *message() const {
+ return message_.c_str("Could not get exception message in JavaExceptionMessage");
+ }
+
+ private:
+ // non-copyable
+ JavaExceptionMessage(const JavaExceptionMessage &);
+ JavaExceptionMessage &operator=(const JavaExceptionMessage &);
+
+ // Get exception message by calling Java method Throwable.getMessage()
+ static jstring exceptionMessageFromThrowable(JNIEnv *jenv, jthrowable throwable) {
+ jstring jmsg = NULL;
+ if (jenv && throwable) {
+ jenv->ExceptionClear(); // Cannot invoke methods with any pending exceptions
+ jclass throwclz = jenv->GetObjectClass(throwable);
+ if (throwclz) {
+ // All Throwable classes have a getMessage() method, so call it to extract the exception message
+ jmethodID getMessageMethodID = jenv->GetMethodID(throwclz, "getMessage", "()Ljava/lang/String;");
+ if (getMessageMethodID)
+ jmsg = (jstring)jenv->CallObjectMethod(throwable, getMessageMethodID);
+ }
+ if (jmsg == NULL && jenv->ExceptionCheck())
+ jenv->ExceptionClear();
+ }
+ return jmsg;
+ }
+
+ JavaString message_;
+ };
+
+ // C++ Exception class for handling Java exceptions thrown during a director method Java upcall
+ class DirectorException : public std::exception {
+ public:
+
+ // Construct exception from a Java throwable
+ DirectorException(JNIEnv *jenv, jthrowable throwable) : classname_(0), msg_(0) {
+
+ // Call Java method Object.getClass().getName() to obtain the throwable's class name (delimited by '/')
+ if (throwable) {
+ jclass throwclz = jenv->GetObjectClass(throwable);
+ if (throwclz) {
+ jclass clzclz = jenv->GetObjectClass(throwclz);
+ if (clzclz) {
+ jmethodID getNameMethodID = jenv->GetMethodID(clzclz, "getName", "()Ljava/lang/String;");
+ if (getNameMethodID) {
+ jstring jstr_classname = (jstring)(jenv->CallObjectMethod(throwclz, getNameMethodID));
+ // Copy strings, since there is no guarantee that jenv will be active when handled
+ if (jstr_classname) {
+ JavaString jsclassname(jenv, jstr_classname);
+ const char *classname = jsclassname.c_str(0);
+ if (classname)
+ classname_ = copypath(classname);
+ }
+ }
+ }
+ }
+ }
+
+ JavaExceptionMessage exceptionmsg(jenv, throwable);
+ msg_ = copystr(exceptionmsg.message());
+ }
+
+ // More general constructor for handling as a java.lang.RuntimeException
+ DirectorException(const char *msg) : classname_(0), msg_(copystr(msg ? msg : "Unspecified DirectorException message")) {
+ }
+
+ ~DirectorException() throw() {
+ delete[] classname_;
+ delete[] msg_;
+ }
+
+ const char *what() const throw() {
+ return msg_;
+ }
+
+ // Reconstruct and raise/throw the Java Exception that caused the DirectorException
+ // Note that any error in the JNI exception handling results in a Java RuntimeException
+ void raiseJavaException(JNIEnv *jenv) const {
+ if (jenv) {
+ jenv->ExceptionClear();
+
+ jmethodID ctorMethodID = 0;
+ jclass throwableclass = 0;
+ if (classname_) {
+ throwableclass = jenv->FindClass(classname_);
+ if (throwableclass)
+ ctorMethodID = jenv->GetMethodID(throwableclass, "<init>", "(Ljava/lang/String;)V");
+ }
+
+ if (ctorMethodID) {
+ jenv->ThrowNew(throwableclass, what());
+ } else {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, what());
+ }
+ }
+ }
+
+ private:
+ static char *copypath(const char *srcmsg) {
+ char *target = copystr(srcmsg);
+ for (char *c=target; *c; ++c) {
+ if ('.' == *c)
+ *c = '/';
+ }
+ return target;
+ }
+
+ static char *copystr(const char *srcmsg) {
+ char *target = 0;
+ if (srcmsg) {
+ size_t msglen = strlen(srcmsg) + 1;
+ target = new char[msglen];
+ strncpy(target, srcmsg, msglen);
+ }
+ return target;
+ }
+
+ const char *classname_;
+ const char *msg_;
+ };
+
+ // Helper method to determine if a Java throwable matches a particular Java class type
+ SWIGINTERN bool ExceptionMatches(JNIEnv *jenv, jthrowable throwable, const char *classname) {
+ bool matches = false;
+
+ if (throwable && jenv && classname) {
+ // Exceptions need to be cleared for correct behavior.
+ // The caller of ExceptionMatches should restore pending exceptions if desired -
+ // the caller already has the throwable.
+ jenv->ExceptionClear();
+
+ jclass clz = jenv->FindClass(classname);
+ if (clz) {
+ jclass classclz = jenv->GetObjectClass(clz);
+ jmethodID isInstanceMethodID = jenv->GetMethodID(classclz, "isInstance", "(Ljava/lang/Object;)Z");
+ if (isInstanceMethodID) {
+ matches = jenv->CallBooleanMethod(clz, isInstanceMethodID, throwable) != 0;
+ }
+ }
+
+#if defined(DEBUG_DIRECTOR_EXCEPTION)
+ if (jenv->ExceptionCheck()) {
+ // Typically occurs when an invalid classname argument is passed resulting in a ClassNotFoundException
+ JavaExceptionMessage exc(jenv, jenv->ExceptionOccurred());
+ std::cout << "Error: ExceptionMatches: class '" << classname << "' : " << exc.message() << std::endl;
+ }
+#endif
+ }
+ return matches;
+ }
+}
+