// Copyright 2017 The Bazel Authors. All rights reserved.
//
// 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 "src/tools/launcher/java_launcher.h"

#include <memory>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/file_platform.h"
#include "src/main/cpp/util/path_platform.h"
#include "src/main/cpp/util/strings.h"
#include "src/main/native/windows/file.h"
#include "src/main/native/windows/process.h"
#include "src/tools/launcher/util/launcher_util.h"

#if (__cplusplus >= 201703L)
#include <filesystem>  // NOLINT
#endif

namespace bazel {
namespace launcher {

using std::getline;
using std::string;
using std::vector;
using std::wofstream;
using std::wostringstream;
using std::wstring;
using std::wstringstream;

// The runfile path of java binary, eg. local_jdk/bin/java.exe
static constexpr const char* JAVA_BIN_PATH = "java_bin_path";
static constexpr const char* JAR_BIN_PATH = "jar_bin_path";
static constexpr const char* CLASSPATH = "classpath";
static constexpr const char* JAVA_START_CLASS = "java_start_class";
static constexpr const char* JVM_FLAGS = "jvm_flags";

// Check if a string start with a certain prefix.
// If it's true, store the substring without the prefix in value.
// If value is quoted, then remove the quotes.
static bool GetFlagValue(const wstring& str, const wstring& prefix,
                         wstring* value_ptr) {
  if (str.compare(0, prefix.length(), prefix)) {
    return false;
  }
  wstring& value = *value_ptr;
  value = str.substr(prefix.length());
  int len = value.length();
  if (len >= 2 && value[0] == L'"' && value[len - 1] == L'"') {
    value = value.substr(1, len - 2);
  }
  return true;
}

// Parses one launcher flag and updates this object's state accordingly.
//
// Returns true if the flag is a valid launcher flag; false otherwise.
bool JavaBinaryLauncher::ProcessWrapperArgument(const wstring& argument) {
  wstring flag_value;
  if (argument.compare(L"--debug") == 0) {
    wstring default_jvm_debug_port;
    if (GetEnv(L"DEFAULT_JVM_DEBUG_PORT", &default_jvm_debug_port)) {
      this->jvm_debug_port = default_jvm_debug_port;
    } else {
      this->jvm_debug_port = L"5005";
    }
  } else if (GetFlagValue(argument, L"--debug=", &flag_value)) {
    this->jvm_debug_port = flag_value;
  } else if (GetFlagValue(argument, L"--main_advice=", &flag_value)) {
    this->main_advice = flag_value;
  } else if (GetFlagValue(argument, L"--main_advice_classpath=", &flag_value)) {
    this->main_advice_classpath = flag_value;
  } else if (GetFlagValue(argument, L"--jvm_flag=", &flag_value)) {
    this->jvm_flags_cmdline.push_back(flag_value);
  } else if (GetFlagValue(argument, L"--jvm_flags=", &flag_value)) {
    wstringstream flag_value_ss(flag_value);
    wstring item;
    while (getline(flag_value_ss, item, L' ')) {
      this->jvm_flags_cmdline.push_back(item);
    }
  } else if (argument.compare(L"--singlejar") == 0) {
    this->singlejar = true;
  } else if (argument.compare(L"--print_javabin") == 0) {
    this->print_javabin = true;
  } else if (GetFlagValue(argument, L"--classpath_limit=", &flag_value)) {
    this->classpath_limit = std::stoi(flag_value);
  } else {
    return false;
  }
  return true;
}

vector<wstring> JavaBinaryLauncher::ProcessesCommandLine() {
  vector<wstring> args;
  bool first = 1;
  for (const auto& arg : this->GetCommandlineArguments()) {
    // Skip the first argument.
    if (first) {
      first = 0;
      continue;
    }
    wstring flag_value;
    // TODO(pcloudy): Should rename this flag to --native_launcher_flag.
    // But keep it as it is for now to be consistent with the shell script
    // launcher.
    if (GetFlagValue(arg, L"--wrapper_script_flag=", &flag_value)) {
      if (!ProcessWrapperArgument(flag_value)) {
        die(L"invalid wrapper argument '%s'", arg.c_str());
      }
    } else if (!args.empty() || !ProcessWrapperArgument(arg)) {
      args.push_back(arg);
    }
  }
  return args;
}

// Return an absolute normalized path for the directory of manifest jar
static wstring GetManifestJarDir(const wstring& binary_base_path) {
  wstring abs_manifest_jar_dir;
  std::size_t slash = binary_base_path.find_last_of(L"/\\");
  if (slash == wstring::npos) {
    abs_manifest_jar_dir = L"";
  } else {
    abs_manifest_jar_dir = binary_base_path.substr(0, slash);
  }
  if (!blaze_util::IsAbsolute(binary_base_path)) {
    abs_manifest_jar_dir = blaze_util::GetCwdW() + L"\\" + abs_manifest_jar_dir;
  }
  wstring result;
  if (!NormalizePath(abs_manifest_jar_dir, &result)) {
    die(L"GetManifestJarDir Failed");
  }
  return result;
}

static void WriteJarClasspath(const wstring& jar_path,
                              wostringstream* manifest_classpath) {
  *manifest_classpath << L' ';
  for (const auto& x : jar_path) {
    if (isalnum(x) || x == L'.' || x == L'-' || x == L'_' || x == L'~') {
      *manifest_classpath << x;
    } else if (x == L'\\') {
      *manifest_classpath << L"/";
    } else {
      // Replace the character with its 2-digit hexadecimal representation.
      char buffer[4];
      snprintf(buffer, sizeof(buffer), "%02X", x);
      *manifest_classpath << L"%" << buffer;
    }
  }
}

wstring JavaBinaryLauncher::GetJunctionBaseDir() {
  wstring binary_base_path = GetBinaryPathWithExtension(GetLauncherPath());
  wstring result;
  if (!NormalizePath(binary_base_path + L".j", &result)) {
    die(L"Failed to get normalized junction base directory.");
  }
  return result;
}

void JavaBinaryLauncher::DeleteJunctionBaseDir() {
  wstring junction_base_dir_norm = GetJunctionBaseDir();
  if (!DoesDirectoryPathExist(junction_base_dir_norm.c_str())) {
    return;
  }
  vector<wstring> junctions;
  blaze_util::GetAllFilesUnderW(junction_base_dir_norm, &junctions);
  for (const auto& junction : junctions) {
    if (!DeleteDirectoryByPath(junction.c_str())) {
      PrintError(L"Failed to delete junction directory: %hs",
                 GetLastErrorString().c_str());
    }
  }
  if (!DeleteDirectoryByPath(junction_base_dir_norm.c_str())) {
    PrintError(L"Failed to delete junction directory: %hs",
               GetLastErrorString().c_str());
  }
}

wstring JavaBinaryLauncher::CreateClasspathJar(const wstring& classpath) {
  wstring binary_base_path = GetBinaryPathWithoutExtension(GetLauncherPath());
  wstring abs_manifest_jar_dir_norm = GetManifestJarDir(binary_base_path);

  wostringstream manifest_classpath;
  manifest_classpath << L"Class-Path:";
  wstringstream classpath_ss(classpath);
  wstring path, path_norm;

  // A set to store all junctions created.
  // The key is the target path, the value is the junction path.
  std::unordered_map<wstring, wstring> jar_dirs;
  wstring junction_base_dir_norm = GetJunctionBaseDir();
  int junction_count = 0;
  // Make sure the junction base directory doesn't exist already.
  DeleteJunctionBaseDir();
  blaze_util::MakeDirectoriesW(junction_base_dir_norm, 0755);

  while (getline(classpath_ss, path, L';')) {
    if (blaze_util::IsAbsolute(path)) {
      if (!NormalizePath(path, &path_norm)) {
        die(L"CreateClasspathJar failed");
      }

      // If two paths are under different drives, we should create a junction to
      // the jar's directory
      if (path_norm[0] != abs_manifest_jar_dir_norm[0]) {
        wstring jar_dir = GetParentDirFromPath(path_norm);
        wstring jar_base_name = GetBaseNameFromPath(path_norm);
        wstring junction;
        auto search = jar_dirs.find(jar_dir);
        if (search == jar_dirs.end()) {
          junction = junction_base_dir_norm + L"\\" +
                     std::to_wstring(junction_count++);

          wstring error;
          if (bazel::windows::CreateJunction(junction, jar_dir, &error) !=
              bazel::windows::CreateJunctionResult::kSuccess) {
            die(L"CreateClasspathJar failed: %s", error.c_str());
          }

          jar_dirs.insert(std::make_pair(jar_dir, junction));
        } else {
          junction = search->second;
        }
        path_norm = junction + L"\\" + jar_base_name;
      }

      if (!RelativeTo(path_norm, abs_manifest_jar_dir_norm, &path)) {
        die(L"CreateClasspathJar failed");
      }
    }
    WriteJarClasspath(path, &manifest_classpath);
  }

  wstring rand_id = L"-" + GetRandomStr(10);
  // Enable long path support for jar_manifest_file_path.
  wstring jar_manifest_file_path =
      binary_base_path + rand_id + L".jar_manifest";
  blaze_util::AddUncPrefixMaybe(&jar_manifest_file_path);
#if (__cplusplus >= 201703L)
  wofstream jar_manifest_file{std::filesystem::path(jar_manifest_file_path)};
#else
  wofstream jar_manifest_file(jar_manifest_file_path);
#endif
  jar_manifest_file << L"Manifest-Version: 1.0\n";
  // No line in the MANIFEST.MF file may be longer than 72 bytes.
  // A space prefix indicates the line is still the content of the last
  // attribute.
  wstring manifest_classpath_str = manifest_classpath.str();
  for (size_t i = 0; i < manifest_classpath_str.length(); i += 71) {
    if (i > 0) {
      jar_manifest_file << L" ";
    }
    jar_manifest_file << manifest_classpath_str.substr(i, 71) << "\n";
  }
  jar_manifest_file.close();
  if (jar_manifest_file.fail()) {
    die(L"Couldn't write jar manifest file: %s",
        jar_manifest_file_path.c_str());
  }

  // Create the command for generating classpath jar.
  wstring manifest_jar_path = binary_base_path + rand_id + L"-classpath.jar";
  wstring jar_bin = this->Rlocation(this->GetLaunchInfoByKey(JAR_BIN_PATH));
  vector<wstring> arguments;
  arguments.push_back(L"cvfm");
  arguments.push_back(manifest_jar_path);
  arguments.push_back(jar_manifest_file_path);

  if (this->LaunchProcess(jar_bin, arguments, /* suppressOutput */ true) != 0) {
    die(L"Couldn't create classpath jar: %s", manifest_jar_path.c_str());
  }

  // Delete jar_manifest_file after classpath jar is created.
  DeleteFileByPath(jar_manifest_file_path.c_str());

  return manifest_jar_path;
}

ExitCode JavaBinaryLauncher::Launch() {
  // Parse the original command line.
  vector<wstring> remaining_args = this->ProcessesCommandLine();

  // Set JAVA_RUNFILES
  wstring java_runfiles;
  if (!GetEnv(L"JAVA_RUNFILES", &java_runfiles)) {
    java_runfiles = this->GetRunfilesPath();
  }
  SetEnv(L"JAVA_RUNFILES", java_runfiles);

  // Print Java binary path if needed
  wstring java_bin = this->Rlocation(this->GetLaunchInfoByKey(JAVA_BIN_PATH),
                                     /*has_workspace_name =*/true);
  if (this->print_javabin ||
      this->GetLaunchInfoByKey(JAVA_START_CLASS) == L"--print_javabin") {
    wprintf(L"%s\n", java_bin.c_str());
    return 0;
  }

  wostringstream classpath;

  // Run deploy jar if needed, otherwise generate the CLASSPATH by rlocation.
  if (this->singlejar) {
    wstring deploy_jar =
        GetBinaryPathWithoutExtension(GetLauncherPath()) + L"_deploy.jar";
    if (!DoesFilePathExist(deploy_jar.c_str())) {
      die(L"Option --singlejar was passed, but %s does not exist.\n  (You may "
          "need to build it explicitly.)",
          deploy_jar.c_str());
    }
    classpath << deploy_jar << L';';
  } else {
    wstring path;
    // Add main advice classpath if exists
    if (!this->main_advice_classpath.empty()) {
      wstringstream main_advice_classpath_ss(this->main_advice_classpath);
      while (getline(main_advice_classpath_ss, path, L';')) {
        classpath << this->Rlocation(path) << L';';
      }
    }
    wstringstream classpath_ss(this->GetLaunchInfoByKey(CLASSPATH));
    while (getline(classpath_ss, path, L';')) {
      classpath << this->Rlocation(path) << L';';
    }
  }

  // Set jvm debug options
  wostringstream jvm_debug_flags;
  if (!this->jvm_debug_port.empty()) {
    wstring jvm_debug_suspend;
    if (!GetEnv(L"DEFAULT_JVM_DEBUG_SUSPEND", &jvm_debug_suspend)) {
      jvm_debug_suspend = L"y";
    }
    jvm_debug_flags << L"-agentlib:jdwp=transport=dt_socket,server=y";
    jvm_debug_flags << L",suspend=" << jvm_debug_suspend;
    jvm_debug_flags << L",address=" << jvm_debug_port;

    wstring value;
    if (GetEnv(L"PERSISTENT_TEST_RUNNER", &value) && value == L"true") {
      jvm_debug_flags << L",quiet=y";
    }
  }

  // Get jvm flags from JVM_FLAGS environment variable and JVM_FLAGS launch info
  vector<wstring> jvm_flags;
  wstring jvm_flags_env;
  GetEnv(L"JVM_FLAGS", &jvm_flags_env);
  wstring flag;
  wstringstream jvm_flags_env_ss(jvm_flags_env);
  while (getline(jvm_flags_env_ss, flag, L' ')) {
    jvm_flags.push_back(flag);
  }
  wstringstream jvm_flags_launch_info_ss(this->GetLaunchInfoByKey(JVM_FLAGS));
  while (getline(jvm_flags_launch_info_ss, flag, L'\t')) {
    jvm_flags.push_back(flag);
  }

  // Check if TEST_TMPDIR is available to use for scratch.
  wstring test_tmpdir;
  if (GetEnv(L"TEST_TMPDIR", &test_tmpdir) &&
      DoesDirectoryPathExist(test_tmpdir.c_str())) {
    jvm_flags.push_back(L"-Djava.io.tmpdir=" + test_tmpdir);
  }

  // Construct the final command line arguments
  vector<wstring> arguments;
  // Add classpath flags
  arguments.push_back(L"-classpath");
  // Check if CLASSPATH is over classpath length limit.
  // If it does, then we create a classpath jar to pass CLASSPATH value.
  wstring classpath_str = classpath.str();
  wstring classpath_jar = L"";
  if (classpath_str.length() > this->classpath_limit) {
    classpath_jar = CreateClasspathJar(classpath_str);
    arguments.push_back(classpath_jar);
  } else {
    arguments.push_back(classpath_str);
  }
  // Add JVM debug flags
  wstring jvm_debug_flags_str = jvm_debug_flags.str();
  if (!jvm_debug_flags_str.empty()) {
    arguments.push_back(jvm_debug_flags_str);
  }
  // Add JVM flags parsed from env and launch info.
  for (const auto& arg : jvm_flags) {
    arguments.push_back(arg);
  }
  // Add JVM flags parsed from command line.
  for (const auto& arg : this->jvm_flags_cmdline) {
    arguments.push_back(arg);
  }
  // Add main advice class
  if (!this->main_advice.empty()) {
    arguments.push_back(this->main_advice);
  }
  // Add java start class
  arguments.push_back(this->GetLaunchInfoByKey(JAVA_START_CLASS));
  // Add the remaininng arguments, they will be passed to the program.
  for (const auto& arg : remaining_args) {
    arguments.push_back(arg);
  }

  ExitCode exit_code = this->LaunchProcess(java_bin, arguments);

  // Delete classpath jar file after execution.
  if (!classpath_jar.empty()) {
    DeleteFileByPath(classpath_jar.c_str());
    DeleteJunctionBaseDir();
  }

  return exit_code;
}

}  // namespace launcher
}  // namespace bazel
