1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 //
41 //  W A R N I N G
42 //  -------------
43 //
44 // This file is not part of the Qt API.  It exists purely as an
45 // implementation detail.  This header file may change from version to
46 // version without notice, or even be removed.
47 //
48 // We mean it.
49 //
50 
51 #ifndef QJNI_P_H
52 #define QJNI_P_H
53 
54 #include <jni.h>
55 #include <QtCore/private/qglobal_p.h>
56 #include <QtCore/qsharedpointer.h>
57 
58 QT_BEGIN_NAMESPACE
59 
60 struct Q_CORE_EXPORT QJNILocalRefDeleter
61 {
62     static void cleanup(jobject obj);
63 };
64 
65 // To simplify this we only define it for jobjects.
66 typedef QScopedPointer<_jobject, QJNILocalRefDeleter> QJNIScopedLocalRef;
67 
68 class Q_CORE_EXPORT QJNIEnvironmentPrivate
69 {
70 public:
71     QJNIEnvironmentPrivate();
72     ~QJNIEnvironmentPrivate();
73     JNIEnv *operator->();
74     operator JNIEnv*() const;
75     static jclass findClass(const char *className, JNIEnv *env = 0);
76 
77 private:
78     friend class QAndroidJniEnvironment;
79     Q_DISABLE_COPY_MOVE(QJNIEnvironmentPrivate)
80     JNIEnv *jniEnv;
81 };
82 
83 class Q_CORE_EXPORT QJNIObjectData
84 {
85 public:
86     QJNIObjectData();
87     ~QJNIObjectData();
88     jobject m_jobject;
89     jclass m_jclass;
90     bool m_own_jclass;
91     QByteArray m_className;
92 };
93 
94 class Q_CORE_EXPORT QJNIObjectPrivate
95 {
96 public:
97     QJNIObjectPrivate();
98     explicit QJNIObjectPrivate(const char *className);
99     QJNIObjectPrivate(const char *className, const char *sig, ...);
100     explicit QJNIObjectPrivate(jclass clazz);
101     QJNIObjectPrivate(jclass clazz, const char *sig, ...);
102     // In most cases you should never call this function with a local ref. unless you intend
103     // to manage the local ref. yourself.
104     // NOTE: see fromLocalRef() for converting a local ref. to QJNIObjectPrivate.
105     explicit QJNIObjectPrivate(jobject globalRef);
106 
107     template <typename T>
108     T callMethod(const char *methodName,
109                  const char *sig,
110                  ...) const;
111     template <typename T>
112     T callMethod(const char *methodName) const;
113     template <typename T>
114     QJNIObjectPrivate callObjectMethod(const char *methodName) const;
115     QJNIObjectPrivate callObjectMethod(const char *methodName,
116                                        const char *sig,
117                                        ...) const;
118     template <typename T>
119     static T callStaticMethod(const char *className,
120                               const char *methodName,
121                               const char *sig, ...);
122     template <typename T>
123     static T callStaticMethod(const char *className,
124                               const char *methodName);
125     template <typename T>
126     static T callStaticMethod(jclass clazz,
127                               const char *methodName,
128                               const char *sig, ...);
129     template <typename T>
130     static T callStaticMethod(jclass clazz,
131                               const char *methodName);
132     static QJNIObjectPrivate callStaticObjectMethod(const char *className,
133                                              const char *methodName,
134                                              const char *sig, ...);
135 
136     static QJNIObjectPrivate callStaticObjectMethod(jclass clazz,
137                                              const char *methodName,
138                                              const char *sig, ...);
139 
140     template <typename T>
141     T getField(const char *fieldName) const;
142     template <typename T>
143     static T getStaticField(const char *className, const char *fieldName);
144     template <typename T>
145     static T getStaticField(jclass clazz, const char *fieldName);
146 
147     QJNIObjectPrivate getObjectField(const char *fieldName, const char *sig) const;
148     static QJNIObjectPrivate getStaticObjectField(const char *className,
149                                                   const char *fieldName,
150                                                   const char *sig);
151     static QJNIObjectPrivate getStaticObjectField(jclass clazz,
152                                                   const char *fieldName,
153                                                   const char *sig);
154 
155     template <typename T>
156     void setField(const char *fieldName, T value);
157     template <typename T>
158     void setField(const char *fieldName, const char *sig, T value);
159     template <typename T>
160     static void setStaticField(const char *className,
161                                const char *fieldName,
162                                T value);
163     template <typename T>
164     static void setStaticField(const char *className,
165                                const char *fieldName,
166                                const char *sig,
167                                T value);
168     template <typename T>
169     static void setStaticField(jclass clazz,
170                                const char *fieldName,
171                                const char *sig,
172                                T value);
173 
174     template <typename T>
175     static void setStaticField(jclass clazz,
176                                const char *fieldName,
177                                T value);
178 
179     static QJNIObjectPrivate fromString(const QString &string);
180     QString toString() const;
181 
182     static bool isClassAvailable(const char *className);
183     bool isValid() const;
184     jobject object() const { return d->m_jobject; }
185 
186     template <typename T>
187     inline QJNIObjectPrivate &operator=(T o)
188     {
189         jobject jobj = static_cast<jobject>(o);
190         if (!isSameObject(jobj)) {
191             d = QSharedPointer<QJNIObjectData>::create();
192             if (jobj) {
193                 QJNIEnvironmentPrivate env;
194                 d->m_jobject = env->NewGlobalRef(jobj);
195                 jclass objectClass = env->GetObjectClass(jobj);
196                 d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
197                 env->DeleteLocalRef(objectClass);
198             }
199         }
200 
201         return *this;
202     }
203 
204     // This function takes ownership of the jobject and releases the local ref. before returning.
205     static QJNIObjectPrivate fromLocalRef(jobject lref);
206 
207 private:
208     friend class QAndroidJniObject;
209 
210     struct QVaListPrivate { operator va_list &() const { return m_args; } va_list &m_args; };
211 
212     QJNIObjectPrivate(const char *className, const char *sig, const QVaListPrivate &args);
213     QJNIObjectPrivate(jclass clazz, const char *sig, const QVaListPrivate &args);
214 
215     template <typename T>
216     T callMethodV(const char *methodName,
217                    const char *sig,
218                    va_list args) const;
219     QJNIObjectPrivate callObjectMethodV(const char *methodName,
220                                         const char *sig,
221                                         va_list args) const;
222     template <typename T>
223     static T callStaticMethodV(const char *className,
224                                const char *methodName,
225                                const char *sig,
226                                va_list args);
227     template <typename T>
228     static T callStaticMethodV(jclass clazz,
229                                const char *methodName,
230                                const char *sig,
231                                va_list args);
232     static QJNIObjectPrivate callStaticObjectMethodV(const char *className,
233                                                      const char *methodName,
234                                                      const char *sig,
235                                                      va_list args);
236 
237     static QJNIObjectPrivate callStaticObjectMethodV(jclass clazz,
238                                                      const char *methodName,
239                                                      const char *sig,
240                                                      va_list args);
241 
242     bool isSameObject(jobject obj) const;
243     bool isSameObject(const QJNIObjectPrivate &other) const;
244 
245     friend bool operator==(const QJNIObjectPrivate &, const QJNIObjectPrivate &);
246     friend bool operator!=(const QJNIObjectPrivate&, const QJNIObjectPrivate&);
247     template <typename T> friend bool operator!=(const QJNIObjectPrivate&, T);
248     template <typename T> friend bool operator==(const QJNIObjectPrivate&, T);
249     template <typename T> friend bool operator!=(T, const QJNIObjectPrivate&);
250     template <typename T> friend bool operator==(T, const QJNIObjectPrivate&);
251 
252     QSharedPointer<QJNIObjectData> d;
253 };
254 
255 inline bool operator==(const QJNIObjectPrivate&obj1, const QJNIObjectPrivate&obj2)
256 {
257     return obj1.isSameObject(obj2);
258 }
259 
260 inline bool operator!=(const QJNIObjectPrivate&obj1, const QJNIObjectPrivate&obj2)
261 {
262     return !obj1.isSameObject(obj2);
263 }
264 
265 template <typename T>
266 inline bool operator==(const QJNIObjectPrivate &obj1, T obj2)
267 {
268     return obj1.isSameObject(static_cast<jobject>(obj2));
269 }
270 
271 template <typename T>
272 inline bool operator==(T obj1, const QJNIObjectPrivate &obj2)
273 {
274     return obj2.isSameObject(static_cast<jobject>(obj1));
275 }
276 
277 template <typename T>
278 inline bool operator!=(const QJNIObjectPrivate &obj1, T obj2)
279 {
280     return !obj1.isSameObject(obj2);
281 }
282 
283 template <typename T>
284 inline bool operator!=(T obj1, const QJNIObjectPrivate &obj2)
285 {
286     return !obj2.isSameObject(obj1);
287 }
288 
289 QT_END_NAMESPACE
290 
291 #endif // QJNI_P_H
292