Upstream version 1.3.40
[profile/ivi/swig.git] / Lib / java / director.swg
1 /* -----------------------------------------------------------------------------
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * director.swg
6  *
7  * This file contains support for director classes that proxy
8  * method calls from C++ to Java extensions.
9  * ----------------------------------------------------------------------------- */
10
11 #ifdef __cplusplus
12
13 #if defined(DEBUG_DIRECTOR_OWNED)
14 #include <iostream>
15 #endif
16
17 namespace Swig {
18   /* Java object wrapper */
19   class JObjectWrapper {
20   public:
21     JObjectWrapper() : jthis_(NULL), weak_global_(true) {
22     }
23
24     ~JObjectWrapper() {
25       jthis_ = NULL;
26       weak_global_ = true;
27     }
28
29     bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) {
30       if (!jthis_) {
31         weak_global_ = weak_global;
32         if (jobj)
33           jthis_ = ((weak_global_ || !mem_own) ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj));
34 #if defined(DEBUG_DIRECTOR_OWNED)
35         std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl;
36 #endif
37         return true;
38       } else {
39 #if defined(DEBUG_DIRECTOR_OWNED)
40         std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl;
41 #endif
42         return false;
43       }
44     }
45
46     jobject get(JNIEnv *jenv) const {
47 #if defined(DEBUG_DIRECTOR_OWNED)
48       std::cout << "JObjectWrapper::get(";
49       if (jthis_)
50         std::cout << jthis_;
51       else
52         std::cout << "null";
53       std::cout << ") -> return new local ref" << std::endl;
54 #endif
55       return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_);
56     }
57
58     void release(JNIEnv *jenv) {
59 #if defined(DEBUG_DIRECTOR_OWNED)
60       std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "weak global ref" : "global ref") << std::endl;
61 #endif
62       if (jthis_) {
63         if (weak_global_) {
64           if (jenv->IsSameObject(jthis_, NULL) == JNI_FALSE)
65             jenv->DeleteWeakGlobalRef((jweak)jthis_);
66         } else
67           jenv->DeleteGlobalRef(jthis_);
68       }
69
70       jthis_ = NULL;
71       weak_global_ = true;
72     }
73
74     jobject peek() {
75       return jthis_;
76     }
77
78     /* Java proxy releases ownership of C++ object, C++ object is now
79        responsible for destruction (creates NewGlobalRef to pin Java
80        proxy) */
81     void java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
82       if (take_or_release) {  /* Java takes ownership of C++ object's lifetime. */
83         if (!weak_global_) {
84           jenv->DeleteGlobalRef(jthis_);
85           jthis_ = jenv->NewWeakGlobalRef(jself);
86           weak_global_ = true;
87         }
88       } else { /* Java releases ownership of C++ object's lifetime */
89         if (weak_global_) {
90           jenv->DeleteWeakGlobalRef((jweak)jthis_);
91           jthis_ = jenv->NewGlobalRef(jself);
92           weak_global_ = false;
93         }
94       }
95     }
96
97   private:
98     /* pointer to Java object */
99     jobject jthis_;
100     /* Local or global reference flag */
101     bool weak_global_;
102   };
103
104   /* director base class */
105   class Director {
106     /* pointer to Java virtual machine */
107     JavaVM *swig_jvm_;
108
109   protected:
110 #if defined (_MSC_VER) && (_MSC_VER<1300)
111     class JNIEnvWrapper;
112     friend class JNIEnvWrapper;
113 #endif
114     /* Utility class for managing the JNI environment */
115     class JNIEnvWrapper {
116       const Director *director_;
117       JNIEnv *jenv_;
118     public:
119       JNIEnvWrapper(const Director *director) : director_(director), jenv_(0) {
120 #if defined(SWIG_JAVA_ATTACH_CURRENT_THREAD_AS_DAEMON)
121         // Attach a daemon thread to the JVM. Useful when the JVM should not wait for 
122         // the thread to exit upon shutdown. Only for jdk-1.4 and later.
123         director_->swig_jvm_->AttachCurrentThreadAsDaemon((void **) &jenv_, NULL);
124 #else
125         director_->swig_jvm_->AttachCurrentThread((void **) &jenv_, NULL);
126 #endif
127       }
128       ~JNIEnvWrapper() {
129 #if !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD)
130         // Some JVMs, eg jdk-1.4.2 and lower on Solaris have a bug and crash with the DetachCurrentThread call.
131         // However, without this call, the JVM hangs on exit when the thread was not created by the JVM and creates a memory leak.
132         director_->swig_jvm_->DetachCurrentThread();
133 #endif
134       }
135       JNIEnv *getJNIEnv() const {
136         return jenv_;
137       }
138     };
139
140     /* Java object wrapper */
141     JObjectWrapper swig_self_;
142
143     /* Disconnect director from Java object */
144     void swig_disconnect_director_self(const char *disconn_method) {
145       JNIEnvWrapper jnienv(this) ;
146       JNIEnv *jenv = jnienv.getJNIEnv() ;
147       jobject jobj = swig_self_.peek();
148 #if defined(DEBUG_DIRECTOR_OWNED)
149       std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl;
150 #endif
151       if (jobj && jenv->IsSameObject(jobj, NULL) == JNI_FALSE) {
152         jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V");
153         if (disconn_meth) {
154 #if defined(DEBUG_DIRECTOR_OWNED)
155           std::cout << "Swig::Director::disconnect_director_self upcall to " << disconn_method << std::endl;
156 #endif
157           jenv->CallVoidMethod(jobj, disconn_meth);
158         }
159       }
160     }
161
162   public:
163     Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) NULL), swig_self_() {
164       /* Acquire the Java VM pointer */
165       jenv->GetJavaVM(&swig_jvm_);
166     }
167
168     virtual ~Director() {
169       JNIEnvWrapper jnienv(this) ;
170       JNIEnv *jenv = jnienv.getJNIEnv() ;
171       swig_self_.release(jenv);
172     }
173
174     bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) {
175       return swig_self_.set(jenv, jself, mem_own, weak_global);
176     }
177
178     jobject swig_get_self(JNIEnv *jenv) const {
179       return swig_self_.get(jenv);
180     }
181
182     // Change C++ object's ownership, relative to Java
183     void swig_java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
184       swig_self_.java_change_ownership(jenv, jself, take_or_release);
185     }
186   };
187 }
188
189 #endif /* __cplusplus */
190
191