// 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"

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' ';
  if (jar_path.find_first_of(L" \\") != wstring::npos) {
    for (const auto& x : jar_path) {
      if (x == L' ') {
        *manifest_classpath << L"%20";
      }
      if (x == L'\\') {
        *manifest_classpath << L"/";
      } else {
        *manifest_classpath << x;
      }
    }
  } else {
    *manifest_classpath << jar_path;
  }
}

wstring JavaBinaryLauncher::GetJunctionBaseDir() {
  wstring binary_base_path =
      GetBinaryPathWithExtension(this->GetCommandlineArguments()[0]);
  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(this->GetCommandlineArguments()[0]);
  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);
  wofstream jar_manifest_file(jar_manifest_file_path);
  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(this->GetCommandlineArguments()[0]) +
        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 {
    // Add main advice classpath if exists
    if (!this->main_advice_classpath.empty()) {
      classpath << this->main_advice_classpath << L';';
    }
    wstring path;
    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);
  }

  vector<wstring> escaped_arguments;
  // Quote the arguments if having spaces
  for (const auto& arg : arguments) {
    escaped_arguments.push_back(bazel::windows::WindowsEscapeArg(arg));
  }

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

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

  return exit_code;
}

}  // namespace launcher
}  // namespace bazel
