/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "JniConstants.h"

#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>

#define LOG_TAG "JniConstants"
#include "ALog-priv.h"

// jclass constants list:
//   <class, signature, androidOnly>

#define JCLASS_CONSTANTS_LIST(V)                                            \
  V(FileDescriptor, "java/io/FileDescriptor", false)                        \
  V(NIOAccess, "java/nio/NIOAccess", true)                                  \
  V(NioBuffer, "java/nio/Buffer", false)

// jmethodID's of public methods constants list:
//   <Class, method, method-string, signature, is_static>
#define JMETHODID_CONSTANTS_LIST(V)                                                         \
  V(FileDescriptor, init, "<init>", "()V", false)                                           \
  V(NIOAccess, getBaseArray, "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;", true) \
  V(NIOAccess, getBaseArrayOffset, "getBaseArrayOffset", "(Ljava/nio/Buffer;)I", true)      \
  V(NioBuffer, array, "array", "()Ljava/lang/Object;", false)                               \
  V(NioBuffer, arrayOffset, "arrayOffset", "()I", false)

// jfieldID constants list:
//   <Class, field, signature, is_static>
#define JFIELDID_CONSTANTS_LIST(V)                                          \
  V(FileDescriptor, descriptor, "I", false)                                 \
  V(NioBuffer, _elementSizeShift, "I", false)                               \
  V(NioBuffer, address, "J", false)                                         \
  V(NioBuffer, limit, "I", false)                                           \
  V(NioBuffer, position, "I", false)

#define CLASS_NAME(cls)             g_ ## cls
#define METHOD_NAME(cls, method)    g_ ## cls ## _ ## method
#define FIELD_NAME(cls, field)      g_ ## cls ## _ ## field

//
// Declare storage for cached classes, methods and fields.
//

#define JCLASS_DECLARE_STORAGE(cls, ...)                                    \
  static jclass CLASS_NAME(cls) = NULL;
JCLASS_CONSTANTS_LIST(JCLASS_DECLARE_STORAGE)
#undef JCLASS_DECLARE_STORAGE

#define JMETHODID_DECLARE_STORAGE(cls, method, ...)                         \
  static jmethodID METHOD_NAME(cls, method) = NULL;
JMETHODID_CONSTANTS_LIST(JMETHODID_DECLARE_STORAGE)
#undef JMETHODID_DECLARE_STORAGE

#define JFIELDID_DECLARE_STORAGE(cls, field, ...)                           \
  static jfieldID FIELD_NAME(cls, field) = NULL;
JFIELDID_CONSTANTS_LIST(JFIELDID_DECLARE_STORAGE)
#undef JFIELDID_DECLARE_STORAGE

//
// Helper methods
//

static jclass FindClass(JNIEnv* env, const char* signature, bool androidOnly) {
    jclass cls = (*env)->FindClass(env, signature);
    if (cls == NULL) {
        ALOG_ALWAYS_FATAL_IF(!androidOnly, "Class not found: %s", signature);
        return NULL;
    }
    return (*env)->NewGlobalRef(env, cls);
}

static jmethodID FindMethod(JNIEnv* env, jclass cls,
                            const char* name, const char* signature, bool isStatic) {
    jmethodID method;
    if (isStatic) {
        method = (*env)->GetStaticMethodID(env, cls, name, signature);
    } else {
        method = (*env)->GetMethodID(env, cls, name, signature);
    }
    ALOG_ALWAYS_FATAL_IF(method == NULL, "Method not found: %s:%s", name, signature);
    return method;
}

static jfieldID FindField(JNIEnv* env, jclass cls,
                          const char* name, const char* signature, bool isStatic) {
    jfieldID field;
    if (isStatic) {
        field = (*env)->GetStaticFieldID(env, cls, name, signature);
    } else {
        field = (*env)->GetFieldID(env, cls, name, signature);
    }
    ALOG_ALWAYS_FATAL_IF(field == NULL, "Field not found: %s:%s", name, signature);
    return field;
}

static pthread_once_t g_initialized = PTHREAD_ONCE_INIT;
static JNIEnv* g_init_env;

static void InitializeConstants() {
    // Initialize cached classes.
#define JCLASS_INITIALIZE(cls, signature, androidOnly)                      \
    CLASS_NAME(cls) = FindClass(g_init_env, signature, androidOnly);
    JCLASS_CONSTANTS_LIST(JCLASS_INITIALIZE)
#undef JCLASS_INITIALIZE

    // Initialize cached methods.
#define JMETHODID_INITIALIZE(cls, method, name, signature, isStatic)        \
    METHOD_NAME(cls, method) =                                              \
        FindMethod(g_init_env, CLASS_NAME(cls), name, signature, isStatic);
    JMETHODID_CONSTANTS_LIST(JMETHODID_INITIALIZE)
#undef JMETHODID_INITIALIZE

    // Initialize cached fields.
#define JFIELDID_INITIALIZE(cls, field, signature, isStatic)                \
    FIELD_NAME(cls, field) =                                                \
        FindField(g_init_env, CLASS_NAME(cls), #field, signature, isStatic);
    JFIELDID_CONSTANTS_LIST(JFIELDID_INITIALIZE)
#undef JFIELDID_INITIALIZE
}

void EnsureInitialized(JNIEnv* env) {
    // This method has to be called in every cache accesses because library can be built
    // 2 different ways and existing usage for compat version doesn't have a good hook for
    // initialization and is widely used.
    g_init_env = env;
    pthread_once(&g_initialized, InitializeConstants);
}

// API exported by libnativehelper_api.h.

void jniUninitializeConstants() {
    // Uninitialize cached classes, methods and fields.
    //
    // NB we assume the runtime is stopped at this point and do not delete global
    // references.
#define JCLASS_INVALIDATE(cls, ...) CLASS_NAME(cls) = NULL;
    JCLASS_CONSTANTS_LIST(JCLASS_INVALIDATE);
#undef JCLASS_INVALIDATE

#define JMETHODID_INVALIDATE(cls, method, ...) METHOD_NAME(cls, method) = NULL;
    JMETHODID_CONSTANTS_LIST(JMETHODID_INVALIDATE);
#undef JMETHODID_INVALIDATE

#define JFIELDID_INVALIDATE(cls, field, ...) FIELD_NAME(cls, field) = NULL;
    JFIELDID_CONSTANTS_LIST(JFIELDID_INVALIDATE);
#undef JFIELDID_INVALIDATE

    // If jniConstantsUninitialize is called, runtime has shutdown. Reset
    // state as some tests re-start the runtime.
    pthread_once_t o = PTHREAD_ONCE_INIT;
    memcpy(&g_initialized, &o, sizeof(o));
}

//
// Accessors
//

#define JCLASS_ACCESSOR_IMPL(cls, ...)                                      \
jclass JniConstants_ ## cls ## Class(JNIEnv* env) {                         \
    EnsureInitialized(env);                                                 \
    return CLASS_NAME(cls);                                                 \
}
JCLASS_CONSTANTS_LIST(JCLASS_ACCESSOR_IMPL)
#undef JCLASS_ACCESSOR_IMPL

#define JMETHODID_ACCESSOR_IMPL(cls, method, ...)                           \
jmethodID JniConstants_ ## cls ## _ ## method(JNIEnv* env) {                \
    EnsureInitialized(env);                                                 \
    return METHOD_NAME(cls, method);                                        \
}
JMETHODID_CONSTANTS_LIST(JMETHODID_ACCESSOR_IMPL)

#define JFIELDID_ACCESSOR_IMPL(cls, field, ...)                             \
jfieldID JniConstants_ ## cls ## _ ## field(JNIEnv* env) {                  \
    EnsureInitialized(env);                                                 \
    return FIELD_NAME(cls, field);                                          \
}
JFIELDID_CONSTANTS_LIST(JFIELDID_ACCESSOR_IMPL)
