text: /*
   * copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
   *
   * This file is part of jni4android.
   *
   * jni4android is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
   * jni4android is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with jni4android; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "j4a_base.h"
  #include "j4a/class/android/os/Build.h"
  
  /********************
   * Exception Handle
   ********************/
  
  bool J4A_ExceptionCheck__throwAny(JNIEnv *env)
  {
      if ((*env)->ExceptionCheck(env)) {
          (*env)->ExceptionDescribe(env);
          return true;
      }
  
      return false;
  }
  
  bool J4A_ExceptionCheck__catchAll(JNIEnv *env)
  {
      if ((*env)->ExceptionCheck(env)) {
          (*env)->ExceptionDescribe(env);
          (*env)->ExceptionClear(env);
          return true;
      }
  
      return false;
  }
  
  int J4A_ThrowExceptionOfClass(JNIEnv* env, jclass clazz, const char* msg)
  {
      if ((*env)->ThrowNew(env, clazz, msg) != JNI_OK)
          J4A_ALOGE("%s: Failed: msg: '%s'\n", __func__, msg);
  
      return 0;
  }
  
  int J4A_ThrowException(JNIEnv* env, const char* class_sign, const char* msg)
  {
      int ret = -1;
  
      if (J4A_ExceptionCheck__catchAll(env)) {
          J4A_ALOGE("pending exception throwed.\n");
      }
  
      jclass exceptionClass = J4A_FindClass__catchAll(env, class_sign);
      if (exceptionClass == NULL) {
          J4A_FUNC_FAIL_TRACE();
          ret = -1;
          goto fail;
      }
  
      ret = J4A_ThrowExceptionOfClass(env, exceptionClass, msg);
      if (ret) {
          J4A_FUNC_FAIL_TRACE();
          goto fail;
      }
  
      ret = 0;
  fail:
      J4A_DeleteLocalRef__p(env, &exceptionClass);
      return ret;
  }
  
  int J4A_ThrowIllegalStateException(JNIEnv *env, const char* msg)
  {
      return J4A_ThrowException(env, "java/lang/IllegalStateException", msg);
  }
  
  /********************
   * References
   ********************/
  
  jclass J4A_NewGlobalRef__catchAll(JNIEnv *env, jobject obj)
  {
      jclass obj_global = (*env)->NewGlobalRef(env, obj);
      if (J4A_ExceptionCheck__catchAll(env) || !(obj_global)) {
          J4A_FUNC_FAIL_TRACE();
          goto fail;
      }
  
  fail:
      return obj_global;
  }
  
  void J4A_DeleteLocalRef(JNIEnv *env, jobject obj)
  {
      if (!obj)
          return;
      (*env)->DeleteLocalRef(env, obj);
  }
  
  void J4A_DeleteLocalRef__p(JNIEnv *env, jobject *obj)
  {
      if (!obj)
          return;
      J4A_DeleteLocalRef(env, *obj);
      *obj = NULL;
  }
  
  void J4A_DeleteGlobalRef(JNIEnv *env, jobject obj)
  {
      if (!obj)
          return;
      (*env)->DeleteGlobalRef(env, obj);
  }
  
  void J4A_DeleteGlobalRef__p(JNIEnv *env, jobject *obj)
  {
      if (!obj)
          return;
      J4A_DeleteGlobalRef(env, *obj);
      *obj = NULL;
  }
  
  void J4A_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *c_str)
  {
      if (!str || !c_str)
          return;
      (*env)->ReleaseStringUTFChars(env, str, c_str);
  }
  
  void J4A_ReleaseStringUTFChars__p(JNIEnv *env, jstring str, const char **c_str)
  {
      if (!str || !c_str)
          return;
      J4A_ReleaseStringUTFChars(env, str, *c_str);
      *c_str = NULL;
  }
  
  /********************
   * Class Load
   ********************/
  
  jclass J4A_FindClass__catchAll(JNIEnv *env, const char *class_sign)
  {
      jclass clazz = (*env)->FindClass(env, class_sign);
      if (J4A_ExceptionCheck__catchAll(env) || !(clazz)) {
          J4A_FUNC_FAIL_TRACE();
          clazz = NULL;
          goto fail;
      }
  
  fail:
      return clazz;
  }
  
  jclass J4A_FindClass__asGlobalRef__catchAll(JNIEnv *env, const char *class_sign)
  {
      jclass clazz_global = NULL;
      jclass clazz = J4A_FindClass__catchAll(env, class_sign);
      if (!clazz) {
          J4A_FUNC_FAIL_TRACE1(class_sign);
          goto fail;
      }
  
      clazz_global = J4A_NewGlobalRef__catchAll(env, clazz);
      if (!clazz_global) {
          J4A_FUNC_FAIL_TRACE1(class_sign);
          goto fail;
      }
  
  fail:
      J4A_DeleteLocalRef__p(env, &clazz);
      return clazz_global;
  }
  
  jmethodID J4A_GetMethodID__catchAll(JNIEnv *env, jclass clazz, const char *method_name, const char *method_sign)
  {
      jmethodID method_id = (*env)->GetMethodID(env, clazz, method_name, method_sign);
      if (J4A_ExceptionCheck__catchAll(env) || !method_id) {
          J4A_FUNC_FAIL_TRACE2(method_name, method_sign);
          method_id = NULL;
          goto fail;
      }
  
  fail:
      return method_id;
  }
  
  jmethodID J4A_GetStaticMethodID__catchAll(JNIEnv *env, jclass clazz, const char *method_name, const char *method_sign)
  {
      jmethodID method_id = (*env)->GetStaticMethodID(env, clazz, method_name, method_sign);
      if (J4A_ExceptionCheck__catchAll(env) || !method_id) {
          J4A_FUNC_FAIL_TRACE2(method_name, method_sign);
          method_id = NULL;
          goto fail;
      }
  
  fail:
      return method_id;
  }
  
  jfieldID J4A_GetFieldID__catchAll(JNIEnv *env, jclass clazz, const char *field_name, const char *field_sign)
  {
      jfieldID field_id = (*env)->GetFieldID(env, clazz, field_name, field_sign);
      if (J4A_ExceptionCheck__catchAll(env) || !field_id) {
          J4A_FUNC_FAIL_TRACE2(field_name, field_sign);
          field_id = NULL;
          goto fail;
      }
  
  fail:
      return field_id;
  }
  
  jfieldID J4A_GetStaticFieldID__catchAll(JNIEnv *env, jclass clazz, const char *field_name, const char *field_sign)
  {
      jfieldID field_id = (*env)->GetStaticFieldID(env, clazz, field_name, field_sign);
      if (J4A_ExceptionCheck__catchAll(env) || !field_id) {
          J4A_FUNC_FAIL_TRACE2(field_name, field_sign);
          field_id = NULL;
          goto fail;
      }
  
  fail:
      return field_id;
  }
  
  /********************
   * Misc Functions
   ********************/
  
  jbyteArray J4A_NewByteArray__catchAll(JNIEnv *env, jsize capacity)
  {
      jbyteArray local = (*env)->NewByteArray(env, capacity);
      if (J4A_ExceptionCheck__catchAll(env) || !local)
          return NULL;
  
      return local;
  }
  
  jbyteArray J4A_NewByteArray__asGlobalRef__catchAll(JNIEnv *env, jsize capacity)
  {
      jbyteArray local = (*env)->NewByteArray(env, capacity);
      if (J4A_ExceptionCheck__catchAll(env) || !local)
          return NULL;
  
      jbyteArray global = (*env)->NewGlobalRef(env, local);
      J4A_DeleteLocalRef__p(env, &local);
      return global;
  }
  
  int J4A_GetSystemAndroidApiLevel(JNIEnv *env)
  {
      static int SDK_INT = 0;
      if (SDK_INT > 0)
          return SDK_INT;
  
      SDK_INT = J4AC_android_os_Build__VERSION__SDK_INT__get__catchAll(env);
      J4A_ALOGI("API-Level: %d\n", SDK_INT);
      return SDK_INT;
  }
  