// Copyright (C) 2017 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 <android-base/logging.h>
#include <atomic>
#include <dlfcn.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <jni.h>
#include <jvmti.h>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <vector>

namespace wrapagentproperties {

using PropMap = std::unordered_map<std::string, std::string>;
static constexpr const char* kOnLoad = "Agent_OnLoad";
static constexpr const char* kOnAttach = "Agent_OnAttach";
static constexpr const char* kOnUnload = "Agent_OnUnload";
struct ProxyJavaVM;
using AgentLoadFunction = jint (*)(ProxyJavaVM*, const char*, void*);
using AgentUnloadFunction = jint (*)(JavaVM*);

// Global namespace. Shared by every usage of this wrapper unfortunately.
// We need to keep track of them to call Agent_OnUnload.
static std::mutex unload_mutex;

struct Unloader {
  AgentUnloadFunction unload;
};
static std::vector<Unloader> unload_functions;

static jint CreateJvmtiEnv(ProxyJavaVM* vm, void** out_env, jint version);

struct ProxyJavaVM {
  const struct JNIInvokeInterface* functions;
  JavaVM* real_vm;
  PropMap* map;
  void* dlopen_handle;
  AgentLoadFunction load;
  AgentLoadFunction attach;

  ProxyJavaVM(JavaVM* vm, const std::string& agent_lib, PropMap* map)
      : functions(CreateInvokeInterface()),
        real_vm(vm),
        map(map),
        dlopen_handle(dlopen(agent_lib.c_str(), RTLD_LAZY)),
        load(nullptr),
        attach(nullptr) {
    CHECK(dlopen_handle != nullptr) << "unable to open " << agent_lib;
    {
      std::lock_guard<std::mutex> lk(unload_mutex);
      unload_functions.push_back({
        reinterpret_cast<AgentUnloadFunction>(dlsym(dlopen_handle, kOnUnload)),
      });
    }
    attach = reinterpret_cast<AgentLoadFunction>(dlsym(dlopen_handle, kOnAttach));
    load = reinterpret_cast<AgentLoadFunction>(dlsym(dlopen_handle, kOnLoad));
  }

  // TODO Use this to cleanup
  static jint WrapDestroyJavaVM(ProxyJavaVM* vm) {
    return vm->real_vm->DestroyJavaVM();
  }
  static jint WrapAttachCurrentThread(ProxyJavaVM* vm, JNIEnv** env, void* res) {
    return vm->real_vm->AttachCurrentThread(env, res);
  }
  static jint WrapDetachCurrentThread(ProxyJavaVM* vm) {
    return vm->real_vm->DetachCurrentThread();
  }
  static jint WrapAttachCurrentThreadAsDaemon(ProxyJavaVM* vm, JNIEnv** env, void* res) {
    return vm->real_vm->AttachCurrentThreadAsDaemon(env, res);
  }

  static jint WrapGetEnv(ProxyJavaVM* vm, void** out_env, jint version) {
    switch (version) {
      case JVMTI_VERSION:
      case JVMTI_VERSION_1:
      case JVMTI_VERSION_1_1:
      case JVMTI_VERSION_1_2:
        return CreateJvmtiEnv(vm, out_env, version);
      default:
        if ((version & 0x30000000) == 0x30000000) {
          LOG(ERROR) << "Version number 0x" << std::hex << version << " looks like a JVMTI "
                     << "version but it is not one that is recognized. The wrapper might not "
                     << "function correctly! Continuing anyway.";
        }
        return vm->real_vm->GetEnv(out_env, version);
    }
  }

  static JNIInvokeInterface* CreateInvokeInterface() {
    JNIInvokeInterface* out = new JNIInvokeInterface;
    memset(out, 0, sizeof(JNIInvokeInterface));
    out->DestroyJavaVM = reinterpret_cast<jint (*)(JavaVM*)>(WrapDestroyJavaVM);
    out->AttachCurrentThread =
        reinterpret_cast<jint(*)(JavaVM*, JNIEnv**, void*)>(WrapAttachCurrentThread);
    out->DetachCurrentThread = reinterpret_cast<jint(*)(JavaVM*)>(WrapDetachCurrentThread);
    out->GetEnv = reinterpret_cast<jint(*)(JavaVM*, void**, jint)>(WrapGetEnv);
    out->AttachCurrentThreadAsDaemon =
        reinterpret_cast<jint(*)(JavaVM*, JNIEnv**, void*)>(WrapAttachCurrentThreadAsDaemon);
    return out;
  }
};


struct ExtraJvmtiInterface : public jvmtiInterface_1_ {
  ProxyJavaVM* proxy_vm;
  jvmtiInterface_1_ const* original_interface;

  static jvmtiError WrapDisposeEnvironment(jvmtiEnv* env) {
    ExtraJvmtiInterface* funcs = reinterpret_cast<ExtraJvmtiInterface*>(
        const_cast<jvmtiInterface_1_*>(env->functions));
    jvmtiInterface_1_** out_iface = const_cast<jvmtiInterface_1_**>(&env->functions);
    *out_iface = const_cast<jvmtiInterface_1_*>(funcs->original_interface);
    funcs->original_interface->Deallocate(env, reinterpret_cast<unsigned char*>(funcs));
    jvmtiError res = (*out_iface)->DisposeEnvironment(env);
    return res;
  }

  static jvmtiError WrapGetSystemProperty(jvmtiEnv* env, const char* prop, char** out) {
    ExtraJvmtiInterface* funcs = reinterpret_cast<ExtraJvmtiInterface*>(
        const_cast<jvmtiInterface_1_*>(env->functions));
    auto it = funcs->proxy_vm->map->find(prop);
    if (it != funcs->proxy_vm->map->end()) {
      const std::string& val = it->second;
      std::string str_prop(prop);
      jvmtiError res = env->Allocate(val.size() + 1, reinterpret_cast<unsigned char**>(out));
      if (res != JVMTI_ERROR_NONE) {
        return res;
      }
      strcpy(*out, val.c_str());
      return JVMTI_ERROR_NONE;
    } else {
      return funcs->original_interface->GetSystemProperty(env, prop, out);
    }
  }

  static jvmtiError WrapGetSystemProperties(jvmtiEnv* env, jint* cnt, char*** prop_ptr) {
    ExtraJvmtiInterface* funcs = reinterpret_cast<ExtraJvmtiInterface*>(
        const_cast<jvmtiInterface_1_*>(env->functions));
    jint init_cnt;
    char** init_prop_ptr;
    jvmtiError res = funcs->original_interface->GetSystemProperties(env, &init_cnt, &init_prop_ptr);
    if (res != JVMTI_ERROR_NONE) {
      return res;
    }
    std::unordered_set<std::string> all_props;
    for (const auto& p : *funcs->proxy_vm->map) {
      all_props.insert(p.first);
    }
    for (jint i = 0; i < init_cnt; i++) {
      all_props.insert(init_prop_ptr[i]);
      env->Deallocate(reinterpret_cast<unsigned char*>(init_prop_ptr[i]));
    }
    env->Deallocate(reinterpret_cast<unsigned char*>(init_prop_ptr));
    *cnt = all_props.size();
    res = env->Allocate(all_props.size() * sizeof(char*),
                        reinterpret_cast<unsigned char**>(prop_ptr));
    if (res != JVMTI_ERROR_NONE) {
      return res;
    }
    char** out_prop_ptr = *prop_ptr;
    jint i = 0;
    for (const std::string& p : all_props) {
      res = env->Allocate(p.size() + 1, reinterpret_cast<unsigned char**>(&out_prop_ptr[i]));
      if (res != JVMTI_ERROR_NONE) {
        return res;
      }
      strcpy(out_prop_ptr[i], p.c_str());
      i++;
    }
    CHECK_EQ(i, *cnt);
    return JVMTI_ERROR_NONE;
  }

  static jvmtiError WrapSetSystemProperty(jvmtiEnv* env, const char* prop, const char* val) {
    ExtraJvmtiInterface* funcs = reinterpret_cast<ExtraJvmtiInterface*>(
        const_cast<jvmtiInterface_1_*>(env->functions));
    jvmtiError res = funcs->original_interface->SetSystemProperty(env, prop, val);
    if (res != JVMTI_ERROR_NONE) {
      return res;
    }
    auto it = funcs->proxy_vm->map->find(prop);
    if (it != funcs->proxy_vm->map->end()) {
      it->second = val;
    }
    return JVMTI_ERROR_NONE;
  }

  // TODO It would be way better to actually set up a full proxy like we did for JavaVM but the
  // number of functions makes it not worth it.
  static jint SetupProxyJvmtiEnv(ProxyJavaVM* vm, jvmtiEnv* real_env) {
    ExtraJvmtiInterface* new_iface = nullptr;
    if (JVMTI_ERROR_NONE != real_env->Allocate(sizeof(ExtraJvmtiInterface),
                                              reinterpret_cast<unsigned char**>(&new_iface))) {
      LOG(ERROR) << "Could not allocate extra space for new jvmti interface struct";
      return JNI_ERR;
    }
    memcpy(new_iface, real_env->functions, sizeof(jvmtiInterface_1_));
    new_iface->proxy_vm = vm;
    new_iface->original_interface = real_env->functions;

    // Replace these functions with the new ones.
    new_iface->DisposeEnvironment = WrapDisposeEnvironment;
    new_iface->GetSystemProperty = WrapGetSystemProperty;
    new_iface->GetSystemProperties = WrapGetSystemProperties;
    new_iface->SetSystemProperty = WrapSetSystemProperty;

    // Replace the functions table with our new one with replaced functions.
    jvmtiInterface_1_** out_iface = const_cast<jvmtiInterface_1_**>(&real_env->functions);
    *out_iface = new_iface;
    return JNI_OK;
  }
};

static jint CreateJvmtiEnv(ProxyJavaVM* vm, void** out_env, jint version) {
  jint res = vm->real_vm->GetEnv(out_env, version);
  if (res != JNI_OK) {
    LOG(WARNING) << "Could not create jvmtiEnv to proxy!";
    return res;
  }
  return ExtraJvmtiInterface::SetupProxyJvmtiEnv(vm, reinterpret_cast<jvmtiEnv*>(*out_env));
}

enum class StartType {
  OnAttach, OnLoad,
};

static jint CallNextAgent(StartType start,
                          ProxyJavaVM* vm,
                          const std::string& options,
                          void* reserved) {
  // TODO It might be good to set it up so that the library is unloaded even if no jvmtiEnv's are
  // created but this isn't expected to be common so we will just not bother.
  return ((start == StartType::OnLoad) ? vm->load : vm->attach)(vm, options.c_str(), reserved);
}

static std::string substrOf(const std::string& s, size_t start, size_t end) {
  if (end == start) {
    return "";
  } else if (end == std::string::npos) {
    end = s.size();
  }
  return s.substr(start, end - start);
}

static PropMap* ReadPropMap(const std::string& file) {
  std::unique_ptr<PropMap> map(new PropMap);
  std::ifstream prop_file(file, std::ios::in);
  std::string line;
  while (std::getline(prop_file, line)) {
    if (line.size() == 0 || line[0] == '#') {
      continue;
    }
    if (line.find('=') == std::string::npos) {
      LOG(INFO) << "line: " << line << " didn't have a '='";
      return nullptr;
    }
    std::string prop = substrOf(line, 0, line.find('='));
    std::string val = substrOf(line, line.find('=') + 1, std::string::npos);
    LOG(INFO) << "Overriding property " << std::quoted(prop) << " new value is "
              << std::quoted(val);
    map->insert({prop, val});
  }
  return map.release();
}

static bool ParseArgs(const std::string& options,
                      /*out*/std::string* prop_file,
                      /*out*/std::string* agent_lib,
                      /*out*/std::string* agent_options) {
  if (options.find(',') == std::string::npos) {
    LOG(ERROR) << "No agent lib in " << options;
    return false;
  }
  *prop_file = substrOf(options, 0, options.find(','));
  *agent_lib = substrOf(options, options.find(',') + 1, options.find('='));
  if (options.find('=') != std::string::npos) {
    *agent_options = substrOf(options, options.find('=') + 1, std::string::npos);
  } else {
    *agent_options = "";
  }
  return true;
}

static jint AgentStart(StartType start, JavaVM* vm, char* options, void* reserved) {
  std::string agent_lib;
  std::string agent_options;
  std::string prop_file;
  if (!ParseArgs(options, /*out*/ &prop_file, /*out*/ &agent_lib, /*out*/ &agent_options)) {
    return JNI_ERR;
  }
  // It would be good to not leak these but since they will live for almost the whole program run
  // anyway it isn't a huge deal.
  PropMap* map = ReadPropMap(prop_file);
  if (map == nullptr) {
    LOG(ERROR) << "unable to read property file at " << std::quoted(prop_file) << "!";
    return JNI_ERR;
  }
  ProxyJavaVM* proxy = new ProxyJavaVM(vm, agent_lib, map);
  LOG(INFO) << "Chaining to next agent[" << std::quoted(agent_lib) << "] options=["
            << std::quoted(agent_options) << "]";
  return CallNextAgent(start, proxy, agent_options, reserved);
}

// Late attachment (e.g. 'am attach-agent').
extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char* options, void* reserved) {
  return AgentStart(StartType::OnAttach, vm, options, reserved);
}

// Early attachment
// (e.g. 'java -agentpath:/path/to/libwrapagentproperties.so=/path/to/propfile,/path/to/wrapped.so=[ops]').
extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* jvm, char* options, void* reserved) {
  return AgentStart(StartType::OnLoad, jvm, options, reserved);
}

extern "C" JNIEXPORT void JNICALL Agent_OnUnload(JavaVM* jvm) {
  std::lock_guard<std::mutex> lk(unload_mutex);
  for (const Unloader& u : unload_functions) {
    u.unload(jvm);
    // Don't dlclose since some agents expect to still have code loaded after this.
  }
  unload_functions.clear();
}

}  // namespace wrapagentproperties

