MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
jtie_tconv_object_impl.hpp
1 /*
2  Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 /*
18  * jtie_tconv_object_impl.hpp
19  */
20 
21 #ifndef jtie_tconv_object_impl_hpp
22 #define jtie_tconv_object_impl_hpp
23 
24 #include <assert.h> // not using namespaces yet
25 //#include <stdio.h> // not using namespaces yet
26 #include <jni.h>
27 
28 #include "jtie_tconv_object.hpp"
29 #include "jtie_tconv_impl.hpp"
30 #include "jtie_tconv_idcache_impl.hpp"
31 #include "jtie_tconv_utils_impl.hpp"
32 #include "helpers.hpp"
33 
34 // ---------------------------------------------------------------------------
35 // ObjectParam, Target, ObjectResult
36 // ---------------------------------------------------------------------------
37 
38 // XXX cleanup, document
39 
40 // Defines the field info type for Wrapper.cdelegate.
41 JTIE_DEFINE_FIELD_MEMBER_INFO(_Wrapper_cdelegate)
42 
43 // Provides a (cached) access to field Id of Wrapper.cdelegate.
44 //typedef JniMemberId< NO_CACHING, _Wrapper_cdelegate > Wrapper_cdelegate;
45 typedef JniMemberId< WEAK_CACHING, _Wrapper_cdelegate > Wrapper_cdelegate;
46 //typedef JniMemberId< STRONG_CACHING, _Wrapper_cdelegate > Wrapper_cdelegate;
47 
48 // XXX consider changing
49 //template< typename C > struct ObjectParam< _jtie_Object *, C * > {
50 // to
51 //template< typename J, typename C > struct ObjectParam< J *, C * > {
52 //
53 // same for Target, Result
54 
55 // Implements the mapping of jtie_Objects parameters.
56 template< typename J, typename C >
57 struct ObjectParam;
58 
59 // Implements the mapping of jtie_Object invocation targets.
60 template< typename J, typename C >
61 struct Target;
62 
63 // Implements the mapping of jtie_Object results.
64 template< typename J, typename C >
65 struct ObjectResult;
66 
67 // Implements the mapping of jtie_Objects parameters to pointers.
68 template< typename C >
69 struct ObjectParam< _jtie_Object *, C * > {
70  static C *
71  convert(cstatus & s, _jtie_Object * j, JNIEnv * env) {
72  TRACE("C * ObjectParam.convert(cstatus &, _jtie_Object *, JNIEnv *)");
73  // init status to error
74  s = -1;
75  C * c = NULL;
76 
77  if (j == NULL) {
78  // ok
79  s = 0;
80  } else {
81  // get a (local or global) class object reference
82  jclass cls = Wrapper_cdelegate::getClass(env);
83  if (cls == NULL) {
84  // exception pending
85  } else {
86  // get the field ID valid along with the class reference
87  jfieldID fid = Wrapper_cdelegate::getId(env, cls);
88  if (fid == NULL) {
89  // exception pending
90  } else {
91  // get the field's value
92  jlong p = env->GetLongField(j, fid);
93  //printf(" c = %lx\n", (unsigned long)p);
94  if (p == 0L) {
95  const char * m
96  = ("JTie: Java wrapper object must have a"
97  " non-zero delegate when used as target or"
98  " argument in a method call"
99  " (file: " __FILE__ ")");
100  registerException(env, "java/lang/AssertionError", m);
101  } else {
102  // convert jlong to an address via intptr_t (C99)
103  intptr_t ip = static_cast< intptr_t >(p);
104  assert(static_cast< jlong >(ip) == p);
105  c = reinterpret_cast< C * >(ip);
106  //printf(" c = %p\n", c);
107 
108  // ok
109  s = 0;
110  }
111  }
112  // release reference (if needed)
113  Wrapper_cdelegate::releaseRef(env, cls);
114  }
115  }
116  return c;
117  };
118 
119  static void
120  release(C * c, _jtie_Object * j, JNIEnv * env) {
121  TRACE("void ObjectParam.release(C *, _jtie_Object *, JNIEnv *)");
122  //printf(" c = %lx\n", (unsigned long)c);
123  (void)c; (void)j; (void)env;
124  };
125 };
126 
127 // Implements the mapping of jtie_Objects parameters to references.
128 template< typename C >
129 struct ObjectParam< _jtie_Object *, C & > {
130  static C &
131  convert(cstatus & s, _jtie_Object * j, JNIEnv * env) {
132  TRACE("C & ObjectParam.convert(cstatus &, _jtie_Object *, JNIEnv *)");
133 
134  // init return value and status to error
135  s = -1;
136  C * c = NULL;
137 
138  if (j == NULL) {
139  const char * msg
140  = ("JTie: Java argument must not be null when mapped"
141  " to a C reference (file: " __FILE__ ")");
142  registerException(env, "java/lang/IllegalArgumentException", msg);
143  } else {
144  c = ObjectParam< _jtie_Object *, C * >::convert(s, j, env);
145  assert(s != 0 || c != NULL);
146  }
147 
148  // never actually dereferenced if status indicates an error
149  return *c;
150  };
151 
152  static void
153  release(C & c, _jtie_Object * j, JNIEnv * env) {
154  TRACE("void ObjectParam.release(C &, _jtie_Object *, JNIEnv *)");
155  ObjectParam< _jtie_Object *, C * >::release(&c, j, env);
156  };
157 };
158 
159 // Implements the mapping of jtie_Object invocation targets.
160 template< typename C >
161 struct Target< _jtie_Object *, C > {
162  static C &
163  convert(cstatus & s, _jtie_Object * j, JNIEnv * env) {
164  TRACE("C & Target.convert(cstatus &, _jtie_Object *, JNIEnv *)");
165 
166  // init return value and status to error
167  s = -1;
168  C * c = NULL;
169 
170  if (j == NULL) {
171  const char * msg = ("JTie: Java target object of a method call"
172  " must not be null (file: " __FILE__ ")");
173  registerException(env, "java/lang/NullPointerException", msg);
174  } else {
175  // to avoid template instantiation clutter and ambiguities
176  // specialize/delegate to either ObjectParam< _jtie_Object *, C * >
177  // (preferred for smaller type space) or Param< J *, C * >
178  c = ObjectParam< _jtie_Object *, C * >::convert(s, j, env);
179  assert(s != 0 || c != NULL);
180  }
181 
182  // never actually dereferenced if status indicates an error
183  return *c;
184  };
185 
186  static void
187  release(C & c, _jtie_Object * j, JNIEnv * env) {
188  TRACE("void Target.release(C &, _jtie_Object *, JNIEnv *)");
189  // match delegation in convert()
190  ObjectParam< _jtie_Object *, C * >::release(&c, j, env);
191  };
192 };
193 
194 // Implements the mapping of jtie_Object results to pointers.
195 template< typename J, typename C >
196 struct ObjectResult< J *, C * > {
197  // Provides a (cached) access to the method Id of the constructor of J.
198  //typedef JniMemberId< NO_CACHING, J > J_ctor;
199  typedef JniMemberId< WEAK_CACHING, J > J_ctor;
200  //typedef JniMemberId< STRONG_CACHING, J > J_ctor;
201 
202  static J *
203  convert(C * c, JNIEnv * env) {
204  TRACE("J * ObjectResult.convert(JNIEnv *, C *)");
205  J * j = NULL;
206 
207  if (c == NULL) {
208  // ok
209  } else {
210  // get a (local or global) class object reference
211  jclass cls = J_ctor::getClass(env);
212  if (cls == NULL) {
213  // exception pending
214  } else {
215  // get the method ID valid along with the class reference
216  jmethodID cid = J_ctor::getId(env, cls);
217  if (cid == NULL) {
218  // exception pending
219  } else {
220  J * jo = wrapAsJavaObject(cls, cid, c, env);
221  if (jo == NULL) {
222  // exception pending
223  } else {
224  // ok
225  j = jo;
226  }
227  }
228  // release reference (if needed)
229  J_ctor::releaseRef(env, cls);
230  }
231  }
232  return j;
233  }
234 
235 private:
236  // Constructs a Wrapper object of user-defined type.
237  static J *
238  wrapAsJavaObject(jclass cls, jmethodID cid, C * c, JNIEnv * env);
239 };
240 
241 // Implements the mapping of jtie_Object results to references.
242 template< typename J , typename C >
243 struct ObjectResult< J *, C & > {
244  static J *
245  convert(C & c, JNIEnv * env) {
246  TRACE("J * ObjectResult.convert(JNIEnv *, C &)");
247  J * j = NULL; // init to error
248  C * p = &c;
249 
250  if (p == NULL) {
251  const char * msg
252  = ("JTie: returned C reference must not be null"
253  " (e.g., check if memory allocation has failed without"
254  " raising an exception, as can happen with older C++"
255  " compilers?) (file: " __FILE__ ")");
256  registerException(env, "java/lang/AssertionError", msg);
257  } else {
258  // ok
259  j = ObjectResult< J *, C * >::convert(p, env);
260  }
261  return j;
262  }
263 };
264 
265 // ---------------------------------------------------------------------------
266 // Helper functions
267 // ---------------------------------------------------------------------------
268 
269 // Nullifies a Wrapper object's stored address of the native delegate.
270 inline void
271 detachWrapper(_jtie_Object * jo, JNIEnv * env) {
272  // get a (local or global) class object reference
273  // as a precaution, do not use env->GetObjectClass(jobject), for we
274  // never want to access a field from a subclass that hides the delegate
275  // field in Wrapper
276  jclass cls = Wrapper_cdelegate::getClass(env);
277  if (cls == NULL) {
278  // exception pending
279  } else {
280  // get the field ID valid along with the class reference
281  jfieldID fid = Wrapper_cdelegate::getId(env, cls);
282  if (fid == NULL) {
283  // exception pending
284  } else {
285  // convert address to a jlong via intptr_t (C99)
286  //printf(" p = %p\n", c);
287  intptr_t ip = 0; //reinterpret_cast< intptr_t >((void*)NULL);
288  jlong p = static_cast< jlong >(ip);
289  assert(static_cast< intptr_t >(p) == ip);
290 
291  // set the field's value
292  env->SetLongField(jo, fid, p);
293  }
294  // release reference (if needed)
295  Wrapper_cdelegate::releaseRef(env, cls);
296  }
297 }
298 
299 // Constructs a Wrapper object of user-defined type.
300 template< typename J, typename C >
301 inline J *
302 ObjectResult< J *, C * >::
303 wrapAsJavaObject(jclass cls, jmethodID cid, C * c, JNIEnv * env) {
304  J * j = NULL;
305 
306  // get a (local or global) class object reference
307  // as a precaution, do not use parameter cls, for we never want to access
308  // a field from a subclass that hides the delegate field in Wrapper
309  jclass cls0 = Wrapper_cdelegate::getClass(env);
310  if (cls0 == NULL) {
311  // exception pending
312  } else {
313  // get the field ID valid along with the class reference
314  jfieldID fid = Wrapper_cdelegate::getId(env, cls0);
315  if (fid == NULL) {
316  // exception pending
317  } else {
318  // construct a Wrapper object
319  jobject jo = env->NewObject(cls, cid);
320  if (jo == NULL) {
321  // exception pending
322  } else {
323  // convert address to a jlong via intptr_t (C99)
324  //printf(" p = %p\n", c);
325  intptr_t ip = reinterpret_cast< intptr_t >(c);
326  jlong p = static_cast< jlong >(ip);
327  assert(static_cast< intptr_t >(p) == ip);
328 
329  // set the field's value
330  env->SetLongField(jo, fid, p);
331 
332  // ok
333  j = static_cast< J * >(jo);
334  }
335  }
336  // release reference (if needed)
337  Wrapper_cdelegate::releaseRef(env, cls0);
338  }
339  return j;
340 }
341 
342 // ---------------------------------------------------------------------------
343 // Specializations for Object type conversions
344 // ---------------------------------------------------------------------------
345 
346 // extend jtie_Object specializations to const pointers
347 template< typename J, typename C >
348 struct Param< _jtie_ObjectMapper< J > *, C * const >
349  : Param< _jtie_ObjectMapper< J > *, C * > {};
350 template< typename J, typename C >
351 struct Result< _jtie_ObjectMapper< J > *, C * const >
352  : Result< _jtie_ObjectMapper< J > *, C * > {};
353 
354 // Sufficient to specialize Param<> and Target<> over jtie_Object.
355 
356 // specialize Target (note usage of C, which is a direct type)
357 template< typename J, typename C >
358 struct Target< _jtie_ObjectMapper< J > *, C >
360 
361 // specialize Param for pointers (note usage of C)
362 template< typename J, typename C >
363 struct Param< _jtie_ObjectMapper< J > *, C * >
365 
366 // specialize Param for references (note usage of C)
367 template< typename J, typename C >
368 struct Param< _jtie_ObjectMapper< J > *, C & >
370 
371 // Result<> needs to be specialized over ObjectMapper, which carries
372 // additional information needed for instantiating Java wrapper objects.
373 
374 // specialize Result for pointers (note usage of C)
375 template< typename J, typename C >
376 struct Result< _jtie_ObjectMapper< J > *, C * >
377  : ObjectResult< _jtie_ObjectMapper< J > *, C * > {};
378 
379 // specialize Result for references (note usage of C)
380 template< typename J, typename C >
381 struct Result< _jtie_ObjectMapper< J > *, C & >
382  : ObjectResult< _jtie_ObjectMapper< J > *, C & > {};
383 
384 // ---------------------------------------------------------------------------
385 
386 #endif // jtie_tconv_object_impl_hpp