3
* ====================================================================
4
* Licensed to the Apache Software Foundation (ASF) under one
5
* or more contributor license agreements. See the NOTICE file
6
* distributed with this work for additional information
7
* regarding copyright ownership. The ASF licenses this file
8
* to you under the Apache License, Version 2.0 (the
9
* "License"); you may not use this file except in compliance
10
* with the License. You may obtain a copy of the License at
12
* http://www.apache.org/licenses/LICENSE-2.0
14
* Unless required by applicable law or agreed to in writing,
15
* software distributed under the License is distributed on an
16
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
* KIND, either express or implied. See the License for the
18
* specific language governing permissions and limitations
20
* ====================================================================
24
#ifndef SVN_JAVAHL_JNIWRAPPER_ENV_HPP
25
#define SVN_JAVAHL_JNIWRAPPER_ENV_HPP
31
#ifdef SVN_JAVAHL_DEBUG
32
# ifndef SVN_JAVAHL_JNIWRAPPER_LOG
34
# define SVN_JAVAHL_JNIWRAPPER_LOG(expr) \
35
(std::cerr << expr << std::endl)
36
# endif // SVN_JAVAHL_JNIWRAPPER_LOG
38
# define SVN_JAVAHL_JNIWRAPPER_LOG(expr)
39
#endif // SVN_JAVAHL_DEBUG
44
* A C++ exception object for signalling that a Java exception has
47
* Thrown to unwind the stack while avoiding code clutter when a Java
48
* exception is detected in the JNI environment.
52
class SignalExceptionThrown {};
55
* Auto-initializing proxy for the JNI method ID.
57
* Behaves like a @c jmethodID but automatically initializes to @c NULL.
68
MethodID(jmethodID mid)
72
MethodID(const MethodID& that)
76
MethodID& operator=(jmethodID mid)
82
MethodID& operator=(const MethodID& that)
88
operator jmethodID() const
95
return (NULL != m_mid);
104
* Auto-initializing proxy for the JNI field ID.
106
* Behaves like a @c jfieldID but automatically initializes to @c NULL.
117
FieldID(jfieldID mid)
121
FieldID(const FieldID& that)
125
FieldID& operator=(jfieldID fid)
131
FieldID& operator=(const FieldID& that)
137
operator jfieldID() const
142
operator bool() const
144
return (NULL != m_fid);
152
* Encapsulation of a JNI environment reference.
154
* This class wraps all (relevant) JNI functions and checks for thrown
155
* exceptions, so that call sites don't have to be cluttered with KNI
164
* Constructs an environment object, retrieving the JNI environment
165
* reference from the global JVM reference.
168
: m_env(env_from_jvm())
172
* Given a JNI renvironment reference, constructs an environment object.
174
explicit Env(::JNIEnv* env)
179
* Returns the wrapped JNI environment reference.
181
* This method is present for compatibility with the old-style
182
* native implmentation that needs the raw pointer, and will be
183
* removed presently. Do not use it in new-style code.
185
::JNIEnv* get() const
187
SVN_JAVAHL_JNIWRAPPER_LOG("Warning: Direct access to JNIEnv at "
188
<< __FILE__ << ":" << __LINE__);
192
/** Wrapped JNI function. */
193
jobject NewGlobalRef(jobject obj) const
195
jobject ret = m_env->NewGlobalRef(obj);
196
check_java_exception();
198
throw_java_out_of_memory(error_create_global_reference());
202
/** Wrapped JNI function. */
203
void DeleteGlobalRef(jobject obj) const throw()
205
m_env->DeleteGlobalRef(obj);
208
/** Wrapped JNI function. */
209
void PushLocalFrame(jint capacity) const
211
if (0 > m_env->PushLocalFrame(capacity))
212
throw_java_exception();
215
/** Wrapped JNI function. */
216
void PopLocalFrame() const throw()
218
m_env->PopLocalFrame(NULL);
221
/** Wrapped JNI function. */
222
jint Throw(jthrowable exc) const throw()
224
return m_env->Throw(exc);
227
/** Wrapped JNI function. */
228
jint ThrowNew(jclass cls, const char* message) const throw()
230
return m_env->ThrowNew(cls, message);
233
/** Wrapped JNI function. */
234
jboolean ExceptionCheck() const throw()
236
return m_env->ExceptionCheck();
239
/** Wrapped JNI function. */
240
jthrowable ExceptionOccurred() const throw()
242
return m_env->ExceptionOccurred();
245
/** Wrapped JNI function. */
246
void ExceptionClear() const throw()
248
m_env->ExceptionClear();
251
/** Wrapped JNI function. */
252
jclass FindClass(const char* name) const
254
jclass cls = m_env->FindClass(name);
255
check_java_exception();
259
/** Wrapped JNI function. */
260
jobject NewObject(jclass cls, jmethodID ctor, ...) const
263
va_start(args, ctor);
264
jobject obj = m_env->NewObjectV(cls, ctor, args);
266
check_java_exception();
270
/** Wrapped JNI function. */
271
jclass GetObjectClass(jobject obj) const
273
jclass cls = m_env->GetObjectClass(obj);
274
check_java_exception();
278
/** Wrapped JNI function. */
279
jboolean IsInstanceOf(jobject obj, jclass cls) const throw()
281
return m_env->IsInstanceOf(obj, cls);
284
/** Wrapped JNI function. */
285
jmethodID GetMethodID(jclass cls, const char* name, const char* sig) const
287
jmethodID mid = m_env->GetMethodID(cls, name, sig);
288
check_java_exception();
292
/** Wrapped JNI function. */
293
jmethodID GetStaticMethodID(jclass cls, const char* name,
294
const char* sig) const
296
jmethodID mid = m_env->GetStaticMethodID(cls, name, sig);
297
check_java_exception();
301
/** Wrapped JNI function. */
302
jfieldID GetFieldID(jclass cls, const char* name, const char* sig) const
304
jfieldID fid = m_env->GetFieldID(cls, name, sig);
305
check_java_exception();
309
/** Wrapped JNI function. */
310
jfieldID GetStaticFieldID(jclass cls, const char* name,
311
const char* sig) const
313
jfieldID fid = m_env->GetStaticFieldID(cls, name, sig);
314
check_java_exception();
318
/** Wrapped JNI function. */
319
jstring NewStringUTF(const char* text) const
324
jstring str = m_env->NewStringUTF(text);
325
check_java_exception();
329
/** Wrapped JNI function. */
330
jsize GetStringLength(jstring str) const
332
jsize len = m_env->GetStringLength(str);
333
check_java_exception();
337
/** Wrapped JNI function. */
338
jsize GetStringUTFLength(jstring str) const
340
jsize len = m_env->GetStringUTFLength(str);
341
check_java_exception();
345
/** Wrapped JNI function. */
346
const char* GetStringUTFChars(jstring str, jboolean* is_copy) const
351
const char* text = m_env->GetStringUTFChars(str, is_copy);
352
check_java_exception();
354
throw_java_out_of_memory(error_get_contents_string());
358
/** Wrapped JNI function. */
359
void ReleaseStringUTFChars(jstring str, const char* new_text) const
362
throw std::logic_error(error_release_null_string());
363
m_env->ReleaseStringUTFChars(str, new_text);
366
/** Wrapped JNI function. */
367
void CallVoidMethod(jobject obj, jmethodID mid, ...) const
371
m_env->CallObjectMethodV(obj, mid, args);
373
check_java_exception();
376
/** Boilerplate generator for wrapped JNI functions. */
377
#define SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(T, N) \
378
T Call##N##Method(jobject obj, jmethodID mid, ...) const \
381
va_start(args, mid); \
382
T ret = m_env->Call##N##MethodV(obj, mid, args); \
384
check_java_exception(); \
387
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jobject, Object)
388
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jboolean, Boolean)
389
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jbyte, Byte)
390
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jchar, Char)
391
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jshort, Short)
392
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jint, Int)
393
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jlong, Long)
394
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jfloat, Float)
395
SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jdouble, Double)
396
#undef SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD
398
/** Boilerplate generator for wrapped JNI functions. */
399
#define SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(T, N) \
400
T CallStatic##N##Method(jclass obj, jmethodID mid, ...) const \
403
va_start(args, mid); \
404
T ret = m_env->CallStatic##N##MethodV(obj, mid, args); \
406
check_java_exception(); \
409
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jobject, Object)
410
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jboolean, Boolean)
411
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jbyte, Byte)
412
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jchar, Char)
413
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jshort, Short)
414
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jint, Int)
415
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jlong, Long)
416
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jfloat, Float)
417
SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jdouble, Double)
418
#undef SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD
420
/** Boilerplate generator for wrapped JNI functions. */
421
#define SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(T, N) \
422
T Get##N##Field(jobject obj, jfieldID fid) const \
424
T ret = m_env->Get##N##Field(obj, fid); \
425
check_java_exception(); \
428
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jobject, Object)
429
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jboolean, Boolean)
430
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jbyte, Byte)
431
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jchar, Char)
432
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jshort, Short)
433
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jint, Int)
434
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jlong, Long)
435
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jfloat, Float)
436
SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jdouble, Double)
437
#undef SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD
439
/** Boilerplate generator for wrapped JNI functions. */
440
#define SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(T, N) \
441
void Set##N##Field(jobject obj, jfieldID fid, T val) const \
443
m_env->Set##N##Field(obj, fid, val); \
444
check_java_exception(); \
446
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jobject, Object)
447
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jboolean, Boolean)
448
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jbyte, Byte)
449
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jchar, Char)
450
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jshort, Short)
451
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jint, Int)
452
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jlong, Long)
453
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jfloat, Float)
454
SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jdouble, Double)
455
#undef SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD
457
/** Boilerplate generator for wrapped JNI functions. */
458
#define SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(T, N) \
459
T GetStatic##N##Field(jclass cls, jfieldID fid) const \
461
T ret = m_env->GetStatic##N##Field(cls, fid); \
462
check_java_exception(); \
465
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jobject, Object)
466
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jboolean, Boolean)
467
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jbyte, Byte)
468
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jchar, Char)
469
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jshort, Short)
470
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jint, Int)
471
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jlong, Long)
472
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jfloat, Float)
473
SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jdouble, Double)
474
#undef SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD
476
/** Boilerplate generator for wrapped JNI functions. */
477
#define SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(T, N) \
478
void SetStatic##N##Field(jclass cls, jfieldID fid, T val) const \
480
m_env->SetStatic##N##Field(cls, fid, val); \
481
check_java_exception(); \
483
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jobject, Object)
484
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jboolean, Boolean)
485
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jbyte, Byte)
486
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jchar, Char)
487
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jshort, Short)
488
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jint, Int)
489
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jlong, Long)
490
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jfloat, Float)
491
SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jdouble, Double)
492
#undef SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD
494
/** Wrapped JNI function. */
495
jsize GetArrayLength(jarray array) const
499
return m_env->GetArrayLength(array);
502
/** Wrapped JNI function. */
503
jobjectArray NewObjectArray(jsize length, jclass cls, jobject init) const
505
jobjectArray array = m_env->NewObjectArray(length, cls, init);
507
throw_java_out_of_memory(error_create_object_array());
511
/** Wrapped JNI function. */
512
jobject GetObjectArrayElement(jobjectArray array, jsize index) const
514
jobject obj = m_env->GetObjectArrayElement(array, index);
515
check_java_exception();
519
/** Wrapped JNI function. */
520
void SetObjectArrayElement(jobjectArray array,
521
jsize index, jobject value) const
523
m_env->SetObjectArrayElement(array, index, value);
524
check_java_exception();
527
/** Boilerplate generator for wrapped JNI functions. */
528
#define SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(T, N) \
529
T##Array New##N##Array(jsize length) const \
531
T##Array array = m_env->New##N##Array(length); \
533
throw_java_out_of_memory(error_create_array(#T)); \
536
T* Get##N##ArrayElements(T##Array array, jboolean* is_copy) const \
541
T* data = m_env->Get##N##ArrayElements(array, is_copy); \
542
check_java_exception(); \
544
throw_java_out_of_memory(error_get_contents_array(#N)); \
547
void Release##N##ArrayElements(T##Array array, T* data, jint mode) const \
550
throw std::logic_error(error_release_null_array(#T)); \
551
m_env->Release##N##ArrayElements(array, data, mode); \
554
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jboolean, Boolean)
555
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jbyte, Byte)
556
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jchar, Char)
557
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jshort, Short)
558
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jint, Int)
559
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jlong, Long)
560
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jfloat, Float)
561
SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jdouble, Double)
562
#undef SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY
564
/** Wrapped JNI function. */
565
void* GetDirectBufferAddress(jobject buffer) const
567
void* const addr = m_env->GetDirectBufferAddress(buffer);
568
check_java_exception();
574
static ::JavaVM* m_jvm;
575
static ::JNIEnv* env_from_jvm();
577
void throw_java_exception() const
579
throw SignalExceptionThrown();
582
void check_java_exception() const
584
if (m_env->ExceptionCheck())
585
throw SignalExceptionThrown();
588
void throw_java_out_of_memory(const char* message) const;
590
// We cannont use svn_private_config.h in a header, so we move the
591
// actual message translations into the implementation file.
592
static const char* error_create_global_reference() throw();
593
static const char* error_get_contents_string() throw();
594
static const char* error_release_null_string() throw();
596
static const char* error_create_object_array() throw();
597
static const char* error_create_array(const char* type) throw();
598
static const char* error_get_contents_array(const char* type) throw();
599
static const char* error_release_null_array(const char* type) throw();
602
// This static initializer must only be called by JNI_OnLoad
603
static void static_init(::JavaVM*);
608
* Encapsulation of a JNI local frame.
610
* Used within loop bodies to limit the proliferation of local
611
* references, or anywhere else where such references should be
612
* pre-emptively discarded.
618
static const jint DEFAULT_CAPACITY;
622
* Constructs a local frame, retrieving the JNI environment
623
* reference from the global JVM reference.
625
explicit LocalFrame()
628
m_env.PushLocalFrame(DEFAULT_CAPACITY);
632
* Given a JNI renvironment reference, constructs a local frame.
634
explicit LocalFrame(Env env)
637
m_env.PushLocalFrame(DEFAULT_CAPACITY);
641
* Constructs a local frame with the given initial @a capacity,
642
* retrieving the JNI environment reference from the global JVM
645
explicit LocalFrame(jint capacity)
648
m_env.PushLocalFrame(capacity);
652
* Given a JNI renvironment reference, constructs a local frame with
653
* the given initial @a capacity.
655
explicit LocalFrame(Env env, jint capacity)
658
m_env.PushLocalFrame(capacity);
663
m_env.PopLocalFrame();
667
* Returns the stored enviromnent object.
676
LocalFrame(const LocalFrame&);
677
LocalFrame& operator=(const LocalFrame&);
682
#endif // SVN_JAVAHL_JNIWRAPPER_ENV_HPP