/*
 * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "cds/aotClassLocation.hpp"
#include "cds/aotLogging.hpp"
#include "cds/archiveBuilder.hpp"
#include "cds/cdsConfig.hpp"
#include "cds/dynamicArchive.hpp"
#include "cds/filemap.hpp"
#include "cds/metaspaceShared.hpp"
#include "cds/serializeClosure.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
#include "oops/array.hpp"
#include "oops/objArrayKlass.hpp"
#include "runtime/arguments.hpp"
#include "utilities/classpathStream.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/stringUtils.hpp"

#include <sys/stat.h>
#include <errno.h>

Array<ClassPathZipEntry*>* AOTClassLocationConfig::_dumptime_jar_files = nullptr;
AOTClassLocationConfig* AOTClassLocationConfig::_dumptime_instance = nullptr;
const AOTClassLocationConfig* AOTClassLocationConfig::_runtime_instance = nullptr;

// A ClassLocationStream represents a list of code locations, which can be iterated using
// start() and has_next().
class ClassLocationStream {
protected:
  GrowableArray<const char*> _array;
  int _current;

  // Add one path to this stream.
  void add_one_path(const char* path) {
    _array.append(path);
  }

  // Add all paths specified in cp; cp must be from -classpath or -Xbootclasspath/a.
  void add_paths_in_classpath(const char* cp) {
    ClasspathStream cp_stream(cp);
    while (cp_stream.has_next()) {
      add_one_path(cp_stream.get_next());
    }
  }

public:
  ClassLocationStream() : _array(), _current(0) {}

  void print(outputStream* st) const {
    const char* sep = "";
    for (int i = 0; i < _array.length(); i++) {
      st->print("%s%s", sep, _array.at(i));
      sep = os::path_separator();
    }
  }

  void add(ClassLocationStream& css) {
    for (css.start(); css.has_next();) {
      add_one_path(css.get_next());
    }
  }

  // Iteration
  void start() { _current = 0; }
  bool has_next() const { return _current < _array.length(); }
  const char* get_next() {
    return _array.at(_current++);
  }

  int current() const { return _current; }
  bool is_empty() const { return _array.length() == 0; }
};

class BootCpClassLocationStream : public ClassLocationStream {
public:
  BootCpClassLocationStream() : ClassLocationStream() {
    // Arguments::get_boot_class_path() contains $JAVA_HOME/lib/modules, but we treat that separately
    for (const char* bootcp = Arguments::get_boot_class_path(); *bootcp != '\0'; ++bootcp) {
      if (*bootcp == *os::path_separator()) {
        ++bootcp;
        add_paths_in_classpath(bootcp);
        break;
      }
    }
  }
};

class AppCpClassLocationStream : public ClassLocationStream {
public:
  AppCpClassLocationStream() : ClassLocationStream() {
    const char* appcp = Arguments::get_appclasspath();
    if (strcmp(appcp, ".") == 0) {
      appcp = "";
    }
    add_paths_in_classpath(appcp);
  }
};

class ModulePathClassLocationStream : public ClassLocationStream {
  bool _has_non_jar_modules;
public:
  ModulePathClassLocationStream();
  bool has_non_jar_modules() { return _has_non_jar_modules; }
};

// AllClassLocationStreams is used to iterate over all the code locations that
// are available to the application from -Xbootclasspath, -classpath and --module-path.
// When creating an AOT cache, we store the contents from AllClassLocationStreams
// into an array of AOTClassLocations. See AOTClassLocationConfig::dumptime_init_helper().
// When loading the AOT cache in a production run, we compare the contents of the
// stored AOTClassLocations against the current AllClassLocationStreams to determine whether
// the AOT cache is compatible with the current JVM. See AOTClassLocationConfig::validate().
class AllClassLocationStreams {
  BootCpClassLocationStream _boot_cp;          // Specified by -Xbootclasspath/a
  AppCpClassLocationStream _app_cp;            // Specified by -classpath
  ModulePathClassLocationStream _module_path;  // Specified by --module-path
  ClassLocationStream _boot_and_app_cp;        // Convenience for iterating over both _boot and _app
public:
  BootCpClassLocationStream& boot_cp()             { return _boot_cp; }
  AppCpClassLocationStream& app_cp()               { return _app_cp; }
  ModulePathClassLocationStream& module_path()     { return _module_path; }
  ClassLocationStream& boot_and_app_cp()           { return _boot_and_app_cp; }

  AllClassLocationStreams() : _boot_cp(), _app_cp(), _module_path(), _boot_and_app_cp() {
    _boot_and_app_cp.add(_boot_cp);
    _boot_and_app_cp.add(_app_cp);
  }
};

static bool has_jar_suffix(const char* filename) {
  // In jdk.internal.module.ModulePath.readModule(), it checks for the ".jar" suffix.
  // Performing the same check here.
  const char* dot = strrchr(filename, '.');
  if (dot != nullptr && strcmp(dot + 1, "jar") == 0) {
    return true;
  }
  return false;
}

static int compare_module_path_by_name(const char** p1, const char** p2) {
  return strcmp(*p1, *p2);
}

ModulePathClassLocationStream::ModulePathClassLocationStream() : ClassLocationStream(), _has_non_jar_modules(false) {
  // Note: for handling of --module-path, see
  //   https://openjdk.org/jeps/261#Module-paths
  //   https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/module/ModuleFinder.html#of(java.nio.file.Path...)

  const char* jdk_module_path = Arguments::get_property("jdk.module.path");
  if (jdk_module_path == nullptr) {
    return;
  }

  ClasspathStream cp_stream(jdk_module_path);
  while (cp_stream.has_next()) {
    const char* path = cp_stream.get_next();
    DIR* dirp = os::opendir(path);
    if (dirp == nullptr && errno == ENOTDIR && has_jar_suffix(path)) {
      add_one_path(path);
    } else if (dirp != nullptr) {
      struct dirent* dentry;
      bool found_jar = false;
      while ((dentry = os::readdir(dirp)) != nullptr) {
        const char* file_name = dentry->d_name;
        if (has_jar_suffix(file_name)) {
          size_t full_name_len = strlen(path) + strlen(file_name) + strlen(os::file_separator()) + 1;
          char* full_name = NEW_RESOURCE_ARRAY(char, full_name_len);
          int n = os::snprintf(full_name, full_name_len, "%s%s%s", path, os::file_separator(), file_name);
          assert((size_t)n == full_name_len - 1, "Unexpected number of characters in string");
          add_one_path(full_name);
          found_jar = true;
        } else if (strcmp(file_name, ".") != 0 && strcmp(file_name, "..") != 0) {
          // Found some non jar entries
          _has_non_jar_modules = true;
          log_info(class, path)("Found non-jar path: '%s%s%s'", path, os::file_separator(), file_name);
        }
      }
      if (!found_jar) {
        log_info(class, path)("Found exploded module path: '%s'", path);
        _has_non_jar_modules = true;
      }
      os::closedir(dirp);
    } else {
      _has_non_jar_modules = true;
    }
  }

  _array.sort(compare_module_path_by_name);
}

AOTClassLocation* AOTClassLocation::allocate(JavaThread* current, const char* path, int index,
                                             Group group, bool from_cpattr, bool is_jrt) {
  size_t path_length = 0;
  size_t manifest_length = 0;
  bool check_time = false;
  time_t timestamp = 0;
  int64_t filesize = 0;
  FileType type = FileType::NORMAL;
  // Do not record the actual path of the jrt, as the entire JDK can be moved to a different
  // directory.
  const char* recorded_path = is_jrt ? "" : path;
  path_length = strlen(recorded_path);

  struct stat st;
  if (os::stat(path, &st) == 0) {
    if ((st.st_mode & S_IFMT) == S_IFDIR) {
      type = FileType::DIR;
    } else {
      timestamp = st.st_mtime;
      filesize = st.st_size;

      // The timestamp of $JAVA_HOME/lib/modules is not checked at runtime.
      check_time = !is_jrt;
    }
#ifdef _WINDOWS
  } else if (errno == ERROR_FILE_NOT_FOUND || errno == ERROR_PATH_NOT_FOUND) {
    // On Windows, the errno could be ERROR_PATH_NOT_FOUND (3) in case the directory
    // path doesn't exist.
    type = FileType::NOT_EXIST;
#endif
  } else if (errno == ENOENT) {
    // We allow the file to not exist, as long as it also doesn't exist during runtime.
    type = FileType::NOT_EXIST;
  } else {
    aot_log_error(aot)("Unable to open file %s.", path);
    MetaspaceShared::unrecoverable_loading_error();
  }

  ResourceMark rm(current);
  char* manifest = nullptr;

  if (!is_jrt && type == FileType::NORMAL) {
    manifest = read_manifest(current, path, manifest_length); // resource allocated
  }

  size_t cs_size = header_size() +
    + path_length + 1 /* nul-terminated */
    + manifest_length + 1; /* nul-terminated */

  AOTClassLocation* cs = (AOTClassLocation*)os::malloc(cs_size, mtClassShared);
  memset(cs, 0, cs_size);
  cs->_path_length = path_length;
  cs->_manifest_length = manifest_length;
  cs->_check_time = check_time;
  cs->_from_cpattr = from_cpattr;
  cs->_timestamp = check_time ? timestamp : 0;
  cs->_filesize = filesize;
  cs->_file_type = type;
  cs->_group = group;
  cs->_index = index;

  strcpy(((char*)cs) + cs->path_offset(), recorded_path);
  if (manifest_length > 0) {
    memcpy(((char*)cs) + cs->manifest_offset(), manifest, manifest_length);
  }
  assert(*(cs->manifest() + cs->manifest_length()) == '\0', "should be nul-terminated");

  if (strstr(cs->manifest(), "Multi-Release: true") != nullptr) {
    cs->_is_multi_release_jar = true;
  }

  if (strstr(cs->manifest(), "Extension-List:") != nullptr) {
    vm_exit_during_cds_dumping(err_msg("-Xshare:dump does not support Extension-List in JAR manifest: %s", path));
  }

  return cs;
}

char* AOTClassLocation::read_manifest(JavaThread* current, const char* path, size_t& manifest_length) {
  manifest_length = 0;

  struct stat st;
  if (os::stat(path, &st) != 0) {
    return nullptr;
  }

  ClassPathEntry* cpe = ClassLoader::create_class_path_entry(current, path, &st);
  if (cpe == nullptr) {
    // <path> is a file, but not a JAR file
    return nullptr;
  }
  assert(cpe->is_jar_file(), "should not be called with a directory");

  const char* name = "META-INF/MANIFEST.MF";
  char* manifest;
  jint size;
  manifest = (char*) ((ClassPathZipEntry*)cpe)->open_entry(current, name, &size, true);

  if (manifest == nullptr || size <= 0) { // No Manifest
    manifest_length = 0;
  } else {
    manifest_length = (size_t)size;
  }

  delete cpe;
  return manifest;
}

// The result is resource allocated.
char* AOTClassLocation::get_cpattr() const {
  if (_manifest_length == 0) {
    return nullptr;
  }

  size_t buf_size = _manifest_length + 1;
  char* buf = NEW_RESOURCE_ARRAY(char, buf_size);
  memcpy(buf, manifest(), _manifest_length);
  buf[_manifest_length] = 0; // make sure it's 0-terminated

  // See http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#JAR%20Manifest
  // Replace all CR/LF and CR with LF
  StringUtils::replace_no_expand(buf, "\r\n", "\n");
  // Remove all new-line continuation (remove all "\n " substrings)
  StringUtils::replace_no_expand(buf, "\n ", "");

  const char* tag = "Class-Path: ";
  size_t tag_len = strlen(tag);
  char* found = nullptr;
  char* line_start = buf;
  char* end = buf + _manifest_length;

  assert(*end == 0, "must be nul-terminated");

  while (line_start < end) {
    char* line_end = strchr(line_start, '\n');
    if (line_end == nullptr) {
      // JAR spec require the manifest file to be terminated by a new line.
      break;
    }
    if (strncmp(tag, line_start, tag_len) == 0) {
      if (found != nullptr) {
        // Same behavior as jdk/src/share/classes/java/util/jar/Attributes.java
        // If duplicated entries are found, the last one is used.
        log_warning(aot)("Warning: Duplicate name in Manifest: %s.\n"
                         "Ensure that the manifest does not have duplicate entries, and\n"
                         "that blank lines separate individual sections in both your\n"
                         "manifest and in the META-INF/MANIFEST.MF entry in the jar file:\n%s\n", tag, path());
      }
      found = line_start + tag_len;
      assert(found <= line_end, "sanity");
      *line_end = '\0';
    }
    line_start = line_end + 1;
  }

  return found;
}

AOTClassLocation* AOTClassLocation::write_to_archive() const {
  AOTClassLocation* archived_copy = (AOTClassLocation*)ArchiveBuilder::ro_region_alloc(total_size());
  memcpy((char*)archived_copy, (char*)this, total_size());
  return archived_copy;
}

const char* AOTClassLocation::file_type_string() const {
  switch (_file_type) {
  case FileType::NORMAL: return "file";
  case FileType::DIR: return "dir";
  case FileType::NOT_EXIST: default: return "not-exist";
  }
}

bool AOTClassLocation::check(const char* runtime_path, bool has_aot_linked_classes) const {
  struct stat st;
  if (os::stat(runtime_path, &st) != 0) {
    if (_file_type != FileType::NOT_EXIST) {
      aot_log_warning(aot)("Required classpath entry does not exist: %s", runtime_path);
      return false;
    }
  } else if ((st.st_mode & S_IFMT) == S_IFDIR) {
    if (_file_type == FileType::NOT_EXIST) {
      aot_log_warning(aot)("'%s' must not exist", runtime_path);
      return false;
    }
    if (_file_type == FileType::NORMAL) {
      aot_log_warning(aot)("'%s' must be a file", runtime_path);
      return false;
    }
    if (!os::dir_is_empty(runtime_path)) {
      aot_log_warning(aot)("directory is not empty: '%s'", runtime_path);
      return false;
    }
  } else {
    if (_file_type == FileType::NOT_EXIST) {
      aot_log_warning(aot)("'%s' must not exist", runtime_path);
      if (has_aot_linked_classes) {
        aot_log_error(aot)("CDS archive has aot-linked classes. It cannot be used because the "
                       "file %s exists", runtime_path);
        return false;
      } else {
        aot_log_warning(aot)("Archived non-system classes are disabled because the "
                         "file %s exists", runtime_path);
        FileMapInfo::current_info()->set_has_platform_or_app_classes(false);
        if (DynamicArchive::is_mapped()) {
          FileMapInfo::dynamic_info()->set_has_platform_or_app_classes(false);
        }
      }
    }
    if (_file_type == FileType::DIR) {
      aot_log_warning(aot)("'%s' must be a directory", runtime_path);
      return false;
    }
    bool size_differs = _filesize != st.st_size;
    bool time_differs = _check_time && (_timestamp != st.st_mtime);
    if (size_differs || time_differs) {
      aot_log_warning(aot)("This file is not the one used while building the shared archive file: '%s'%s%s",
                       runtime_path,
                       time_differs ? ", timestamp has changed" : "",
                       size_differs ? ", size has changed" : "");
      return false;
    }
  }

  log_info(class, path)("ok");
  return true;
}

void AOTClassLocationConfig::dumptime_init(JavaThread* current) {
  assert(CDSConfig::is_dumping_archive(), "");
  _dumptime_instance = NEW_C_HEAP_OBJ(AOTClassLocationConfig, mtClassShared);
  _dumptime_instance->dumptime_init_helper(current);
  if (current->has_pending_exception()) {
    // we can get an exception only when we run out of metaspace, but that
    // shouldn't happen this early in bootstrap.
    java_lang_Throwable::print(current->pending_exception(), tty);
    vm_exit_during_initialization("AOTClassLocationConfig::dumptime_init_helper() failed unexpectedly");
  }
}

void AOTClassLocationConfig::dumptime_init_helper(TRAPS) {
  ResourceMark rm;
  GrowableClassLocationArray tmp_array;
  AllClassLocationStreams all_css;

  AOTClassLocation* jrt = AOTClassLocation::allocate(THREAD, ClassLoader::get_jrt_entry()->name(),
                                               0, Group::MODULES_IMAGE,
                                               /*from_cpattr*/false, /*is_jrt*/true);
  log_info(class, path)("path [%d] = (modules image)", tmp_array.length());
  tmp_array.append(jrt);

  parse(THREAD, tmp_array, all_css.boot_cp(), Group::BOOT_CLASSPATH, /*parse_manifest*/true);
  _boot_classpath_end = tmp_array.length();

  parse(THREAD, tmp_array, all_css.app_cp(), Group::APP_CLASSPATH, /*parse_manifest*/true);
  _app_classpath_end = tmp_array.length();

  parse(THREAD, tmp_array, all_css.module_path(), Group::MODULE_PATH, /*parse_manifest*/false);
  _module_end = tmp_array.length();

  _class_locations =  MetadataFactory::new_array<AOTClassLocation*>(ClassLoaderData::the_null_class_loader_data(),
                                                               tmp_array.length(), CHECK);
  for (int i = 0; i < tmp_array.length(); i++) {
    _class_locations->at_put(i, tmp_array.at(i));
  }

  _dumptime_jar_files = MetadataFactory::new_array<ClassPathZipEntry*>(ClassLoaderData::the_null_class_loader_data(),
                                                                       tmp_array.length(), CHECK);
  for (int i = 1; i < tmp_array.length(); i++) {
    ClassPathZipEntry* jar_file = ClassLoader::create_class_path_zip_entry(tmp_array.at(i)->path());
    _dumptime_jar_files->at_put(i, jar_file); // may be null if the path is not a valid JAR file
  }

  const char* lcp = find_lcp(all_css.boot_and_app_cp(), _dumptime_lcp_len);
  if (_dumptime_lcp_len > 0) {
    log_info(class, path)("Longest common prefix = %s (%zu chars)", lcp, _dumptime_lcp_len);
    os::free((void*)lcp);
  } else {
    assert(_dumptime_lcp_len == 0, "sanity");
    log_info(class, path)("Longest common prefix = <none> (0 chars)");
  }

  _has_non_jar_modules = all_css.module_path().has_non_jar_modules();
  _has_platform_classes = false;
  _has_app_classes = false;
  _max_used_index = 0;
}

// Find the longest common prefix of two paths, up to max_lcp_len.
// E.g.   p1 = "/a/b/foo"
//        p2 = "/a/b/bar"
//        max_lcp_len = 3
// -> returns 3
static size_t find_lcp_of_two_paths(const char* p1, const char* p2, size_t max_lcp_len) {
  size_t lcp_len = 0;
  char sep = os::file_separator()[0];
  for (size_t i = 0; ; i++) {
    char c1 = *p1++;
    char c2 = *p2++;
    if (c1 == 0 || c2 == 0 || c1 != c2) {
      break;
    }
    if (c1 == sep) {
      lcp_len = i + 1;
      assert(lcp_len <= max_lcp_len, "sanity");
      if (lcp_len == max_lcp_len) {
        break;
      }
    }
  }
  return lcp_len;
}

// cheap-allocated if lcp_len > 0
const char* AOTClassLocationConfig::find_lcp(ClassLocationStream& css, size_t& lcp_len) {
  const char* first_path = nullptr;
  char sep = os::file_separator()[0];

  for (css.start(); css.has_next(); ) {
    const char* path = css.get_next();
    if (first_path == nullptr) {
      first_path = path;
      const char* p = strrchr(first_path, sep);
      if (p == nullptr) {
        lcp_len = 0;
        return "";
      } else {
        lcp_len = p - first_path + 1;
      }
    } else {
      lcp_len = find_lcp_of_two_paths(first_path, path, lcp_len);
      if (lcp_len == 0) {
        return "";
      }
    }
  }

  if (first_path != nullptr && lcp_len > 0) {
    char* lcp = NEW_C_HEAP_ARRAY(char, lcp_len + 1, mtClassShared);
    lcp[0] = 0;
    strncat(lcp, first_path, lcp_len);
    return lcp;
  } else {
    lcp_len = 0;
    return "";
  }
}

void AOTClassLocationConfig::parse(JavaThread* current, GrowableClassLocationArray& tmp_array,
                                   ClassLocationStream& css, Group group, bool parse_manifest) {
  for (css.start(); css.has_next(); ) {
    add_class_location(current, tmp_array, css.get_next(), group, parse_manifest, /*from_cpattr*/false);
  }
}

void AOTClassLocationConfig::add_class_location(JavaThread* current, GrowableClassLocationArray& tmp_array,
                                                const char* path, Group group, bool parse_manifest, bool from_cpattr) {
  AOTClassLocation* cs = AOTClassLocation::allocate(current, path, tmp_array.length(), group, from_cpattr);
  log_info(class, path)("path [%d] = %s%s", tmp_array.length(), path, from_cpattr ? " (from cpattr)" : "");
  tmp_array.append(cs);

  if (!parse_manifest) {
    // parse_manifest is true for -classpath and -Xbootclasspath/a, and false for --module-path.
    return;
  }

  ResourceMark rm;
  char* cp_attr = cs->get_cpattr(); // resource allocated
  if (cp_attr != nullptr && strlen(cp_attr) > 0) {
    //trace_class_path("found Class-Path: ", cp_attr); FIXME

    char sep = os::file_separator()[0];
    const char* dir_name = cs->path();
    const char* dir_tail = strrchr(dir_name, sep);
#ifdef _WINDOWS
    // On Windows, we also support forward slash as the file separator when locating entries in the classpath entry.
    const char* dir_tail2 = strrchr(dir_name, '/');
    if (dir_tail == nullptr) {
      dir_tail = dir_tail2;
    } else if (dir_tail2 != nullptr && dir_tail2 > dir_tail) {
      dir_tail = dir_tail2;
    }
#endif
    int dir_len;
    if (dir_tail == nullptr) {
      dir_len = 0;
    } else {
      dir_len = pointer_delta_as_int(dir_tail, dir_name) + 1;
    }

    // Split the cp_attr by spaces, and add each file
    char* file_start = cp_attr;
    char* end = file_start + strlen(file_start);

    while (file_start < end) {
      char* file_end = strchr(file_start, ' ');
      if (file_end != nullptr) {
        *file_end = 0;
        file_end += 1;
      } else {
        file_end = end;
      }

      size_t name_len = strlen(file_start);
      if (name_len > 0) {
        ResourceMark rm(current);
        size_t libname_len = dir_len + name_len;
        char* libname = NEW_RESOURCE_ARRAY(char, libname_len + 1);
        int n = os::snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start);
        assert((size_t)n == libname_len, "Unexpected number of characters in string");

        // Avoid infinite recursion when two JAR files refer to each
        // other via cpattr.
        bool found_duplicate = false;
        for (int i = boot_cp_start_index(); i < tmp_array.length(); i++) {
          if (strcmp(tmp_array.at(i)->path(), libname) == 0) {
            found_duplicate = true;
            break;
          }
        }
        if (!found_duplicate) {
          add_class_location(current, tmp_array, libname, group, parse_manifest, /*from_cpattr*/true);
        }
      }

      file_start = file_end;
    }
  }
}

AOTClassLocation const* AOTClassLocationConfig::class_location_at(int index) const {
  return _class_locations->at(index);
}

int AOTClassLocationConfig::get_module_shared_path_index(Symbol* location) const {
  if (location->starts_with("jrt:", 4)) {
    assert(class_location_at(0)->is_modules_image(), "sanity");
    return 0;
  }

  if (num_module_paths() == 0) {
    // The archive(s) were created without --module-path option
    return -1;
  }

  if (!location->starts_with("file:", 5)) {
    return -1;
  }

  // skip_uri_protocol was also called during dump time -- see ClassLoaderExt::process_module_table()
  ResourceMark rm;
  const char* file = ClassLoader::uri_to_path(location->as_C_string());
  for (int i = module_path_start_index(); i < module_path_end_index(); i++) {
    const AOTClassLocation* cs = class_location_at(i);
    assert(!cs->has_unnamed_module(), "must be");
    bool same = os::same_files(file, cs->path());
    log_debug(class, path)("get_module_shared_path_index (%d) %s : %s = %s", i,
                           location->as_C_string(), cs->path(), same ? "same" : "different");
    if (same) {
      return i;
    }
  }
  return -1;
}

// We allow non-empty dirs as long as no classes have been loaded from them.
void AOTClassLocationConfig::check_nonempty_dirs() const {
  assert(CDSConfig::is_dumping_archive(), "sanity");

  bool has_nonempty_dir = false;
  dumptime_iterate([&](AOTClassLocation* cs) {
    if (cs->index() > _max_used_index) {
      return false; // stop iterating
    }
    if (cs->is_dir()) {
      if (!os::dir_is_empty(cs->path())) {
        aot_log_error(aot)("Error: non-empty directory '%s'", cs->path());
        has_nonempty_dir = true;
      }
    }
    return true; // keep iterating
  });

  if (has_nonempty_dir) {
    vm_exit_during_cds_dumping("Cannot have non-empty directory in paths", nullptr);
  }
}

// It's possible to use reflection+setAccessible to call into ClassLoader::defineClass() to
// pretend that a dynamically generated class comes from a JAR file in the classpath.
// Detect such classes so that they can be excluded from the archive.
bool AOTClassLocationConfig::is_valid_classpath_index(int classpath_index, InstanceKlass* ik) {
  if (1 <= classpath_index && classpath_index < length()) {
    ClassPathZipEntry *zip = _dumptime_jar_files->at(classpath_index);
    if (zip != nullptr) {
      JavaThread* current = JavaThread::current();
      ResourceMark rm(current);
      const char* const class_name = ik->name()->as_C_string();
      const char* const file_name = ClassLoader::file_name_for_class_name(class_name,
                                                                          ik->name()->utf8_length());
      if (!zip->has_entry(current, file_name)) {
        aot_log_warning(aot)("class %s cannot be archived because it was not defined from %s as claimed",
                         class_name, zip->name());
        return false;
      }
    }
  }

  return true;
}

AOTClassLocationConfig* AOTClassLocationConfig::write_to_archive() const {
  log_locations(CDSConfig::output_archive_path(), /*is_write=*/true);

  Array<AOTClassLocation*>* archived_copy = ArchiveBuilder::new_ro_array<AOTClassLocation*>(_class_locations->length());
  for (int i = 0; i < _class_locations->length(); i++) {
    archived_copy->at_put(i, _class_locations->at(i)->write_to_archive());
    ArchivePtrMarker::mark_pointer((address*)archived_copy->adr_at(i));
  }

  AOTClassLocationConfig* dumped = (AOTClassLocationConfig*)ArchiveBuilder::ro_region_alloc(sizeof(AOTClassLocationConfig));
  memcpy(dumped, this, sizeof(AOTClassLocationConfig));
  dumped->_class_locations = archived_copy;
  ArchivePtrMarker::mark_pointer(&dumped->_class_locations);

  return dumped;
}

bool AOTClassLocationConfig::check_classpaths(bool is_boot_classpath, bool has_aot_linked_classes,
                                              int index_start, int index_end,
                                              ClassLocationStream& runtime_css,
                                              bool use_lcp_match, const char* runtime_lcp,
                                              size_t runtime_lcp_len) const {
  if (index_start >= index_end && runtime_css.is_empty()) { // nothing to check
    return true;
  }

  ResourceMark rm;
  const char* which = is_boot_classpath ? "boot" : "app";
  LogTarget(Info, class, path) lt;
  if (lt.is_enabled()) {
    LogStream ls(lt);
    ls.print("Checking %s classpath", which);
    ls.print_cr("%s", use_lcp_match ? " (with longest common prefix substitution)" : "");
    ls.print("- expected : '");
    print_dumptime_classpath(ls, index_start, index_end, use_lcp_match, _dumptime_lcp_len, runtime_lcp, runtime_lcp_len);
    ls.print_cr("'");
    ls.print("- actual   : '");
    runtime_css.print(&ls);
    ls.print_cr("'");
  }

  runtime_css.start();
  for (int i = index_start; i < index_end; i++) {
    ResourceMark rm;
    const AOTClassLocation* cs = class_location_at(i);
    const char* effective_dumptime_path = cs->path();
    if (use_lcp_match && _dumptime_lcp_len > 0) {
      effective_dumptime_path = substitute(effective_dumptime_path, _dumptime_lcp_len, runtime_lcp, runtime_lcp_len);
    }

    log_info(class, path)("Checking [%d] '%s' %s%s", i, effective_dumptime_path, cs->file_type_string(),
                          cs->from_cpattr() ? " (from JAR manifest ClassPath attribute)" : "");
    if (!cs->from_cpattr() && file_exists(effective_dumptime_path)) {
      if (!runtime_css.has_next()) {
        aot_log_warning(aot)("%s classpath has fewer elements than expected", which);
        return false;
      }
      const char* runtime_path = runtime_css.get_next();
      while (!file_exists(runtime_path) && runtime_css.has_next()) {
        runtime_path = runtime_css.get_next();
      }
      if (!os::same_files(effective_dumptime_path, runtime_path)) {
        aot_log_warning(aot)("The name of %s classpath [%d] does not match: expected '%s', got '%s'",
                         which, runtime_css.current(), effective_dumptime_path, runtime_path);
        return false;
      }
    }

    if (!cs->check(effective_dumptime_path, has_aot_linked_classes)) {
      return false;
    }
  }

  // Check if the runtime boot classpath has more entries than the one stored in the archive and if the app classpath
  // or the module path requires validation.
  if (is_boot_classpath && runtime_css.has_next() && (need_to_check_app_classpath() || num_module_paths() > 0)) {
    // the check passes if all the extra runtime boot classpath entries are non-existent
    if (check_paths_existence(runtime_css)) {
      aot_log_warning(aot)("boot classpath is longer than expected");
      return false;
    }
  }

  return true;
}

bool AOTClassLocationConfig::file_exists(const char* filename) const{
  struct stat st;
  return (os::stat(filename, &st) == 0 && st.st_size > 0);
}

bool AOTClassLocationConfig::check_paths_existence(ClassLocationStream& runtime_css) const {
  bool exist = false;
  while (runtime_css.has_next()) {
    const char* path = runtime_css.get_next();
    if (file_exists(path)) {
      exist = true;
      break;
    }
  }
  return exist;
}

bool AOTClassLocationConfig::check_module_paths(bool has_aot_linked_classes, int index_start, int index_end,
                                                ClassLocationStream& runtime_css,
                                                bool* has_extra_module_paths) const {
  if (index_start >= index_end && runtime_css.is_empty()) { // nothing to check
    return true;
  }

  ResourceMark rm;

  LogTarget(Info, class, path) lt;
  if (lt.is_enabled()) {
    LogStream ls(lt);
    ls.print_cr("Checking module paths");
    ls.print("- expected : '");
    print_dumptime_classpath(ls, index_start, index_end, false, 0, nullptr, 0);
    ls.print_cr("'");
    ls.print("- actual   : '");
    runtime_css.print(&ls);
    ls.print_cr("'");
  }

  // Make sure all the dumptime module paths exist and are unchanged
  for (int i = index_start; i < index_end; i++) {
    const AOTClassLocation* cs = class_location_at(i);
    const char* dumptime_path = cs->path();

    assert(!cs->from_cpattr(), "not applicable for module path");
    log_info(class, path)("Checking '%s' %s", dumptime_path, cs->file_type_string());

    if (!cs->check(dumptime_path, has_aot_linked_classes)) {
      return false;
    }
  }

  // We allow runtime_css to be a superset of the module paths specified in dumptime. E.g.,
  // Dumptime:    A:C
  // Runtime:     A:B:C
  runtime_css.start();
  for (int i = index_start; i < index_end; i++) {
    const AOTClassLocation* cs = class_location_at(i);
    const char* dumptime_path = cs->path();

    while (true) {
      if (!runtime_css.has_next()) {
        aot_log_warning(aot)("module path has fewer elements than expected");
        *has_extra_module_paths = true;
        return true;
      }
      // Both this->class_locations() and runtime_css are alphabetically sorted. Skip
      // items in runtime_css until we see dumptime_path.
      const char* runtime_path = runtime_css.get_next();
      if (!os::same_files(dumptime_path, runtime_path)) {
        *has_extra_module_paths = true;
        return true;
      } else {
        break;
      }
    }
  }

  if (runtime_css.has_next()) {
    *has_extra_module_paths = true;
  }

  return true;
}

void AOTClassLocationConfig::print_dumptime_classpath(LogStream& ls, int index_start, int index_end,
                                                      bool do_substitute, size_t remove_prefix_len,
                                                      const char* prepend, size_t prepend_len) const {
  const char* sep = "";
  for (int i = index_start; i < index_end; i++) {
    ResourceMark rm;
    const AOTClassLocation* cs = class_location_at(i);
    const char* path = cs->path();
    if (!cs->from_cpattr()) {
      ls.print("%s", sep);
      if (do_substitute) {
        path = substitute(path, remove_prefix_len, prepend, prepend_len);
      }
      ls.print("%s", path);
      sep = os::path_separator();
    }
  }
}

// Returned path is resource-allocated
const char* AOTClassLocationConfig::substitute(const char* path,         // start with this path (which was recorded from dump time)
                                               size_t remove_prefix_len, // remove this number of chars from the beginning
                                               const char* prepend,      // prepend this string
                                               size_t prepend_len) {     // length of the prepended string
  size_t len = strlen(path);
  assert(len > remove_prefix_len, "sanity");
  assert(prepend_len == strlen(prepend), "sanity");
  len -= remove_prefix_len;
  len += prepend_len;

  char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
  int n = os::snprintf(buf, len + 1, "%s%s", prepend, path + remove_prefix_len);
  assert(size_t(n) == len, "sanity");

  return buf;
}

// For performance, we avoid using LCP match if there's at least one
// AOTClassLocation can be matched exactly: this means all other AOTClassLocations must be
// matched exactly.
bool AOTClassLocationConfig::need_lcp_match(AllClassLocationStreams& all_css) const {
  if (app_cp_end_index() == boot_cp_start_index()) {
    // No need to use lcp-match when there are no boot/app paths.
    // TODO: LCP-match not yet supported for modules.
    return false;
  }

  if (need_lcp_match_helper(boot_cp_start_index(), boot_cp_end_index(), all_css.boot_cp()) &&
      need_lcp_match_helper(app_cp_start_index(), app_cp_end_index(), all_css.app_cp())) {
    return true;
  } else {
    return false;
  }
}

bool AOTClassLocationConfig::need_lcp_match_helper(int start, int end, ClassLocationStream& css) const {
  int i = start;
  for (css.start(); i < end && css.has_next(); ) {
    const AOTClassLocation* cs = class_location_at(i++);
    const char* runtime_path = css.get_next();
    if (cs->must_exist() && os::same_files(cs->path(), runtime_path)) {
      // Most likely, we will come to here at the first iteration.
      return false;
    }
  }
  return true;
}

bool AOTClassLocationConfig::validate(const char* cache_filename, bool has_aot_linked_classes, bool* has_extra_module_paths) const {
  ResourceMark rm;
  AllClassLocationStreams all_css;

  log_locations(cache_filename, /*is_write=*/false);

  const char* jrt = ClassLoader::get_jrt_entry()->name();
  log_info(class, path)("Checking [0] (modules image)");
  bool success = class_location_at(0)->check(jrt, has_aot_linked_classes);
  log_info(class, path)("Modules image %s validation: %s", jrt, success ? "passed" : "failed");
  if (!success) {
    return false;
  }
  if (class_locations()->length() == 1) {
    if ((module_path_start_index() >= module_path_end_index()) && Arguments::get_property("jdk.module.path") != nullptr) {
      *has_extra_module_paths = true;
    } else {
      *has_extra_module_paths = false;
    }
  } else {
    bool use_lcp_match = need_lcp_match(all_css);
    const char* runtime_lcp;
    size_t runtime_lcp_len;

    log_info(class, path)("Longest common prefix substitution in boot/app classpath matching: %s",
                          use_lcp_match ? "yes" : "no");
    if (use_lcp_match) {
      runtime_lcp = find_lcp(all_css.boot_and_app_cp(), runtime_lcp_len);
      log_info(class, path)("Longest common prefix: %s (%zu chars)", runtime_lcp, runtime_lcp_len);
    } else {
      runtime_lcp = nullptr;
      runtime_lcp_len = 0;
    }

    success = check_classpaths(true, has_aot_linked_classes, boot_cp_start_index(), boot_cp_end_index(), all_css.boot_cp(),
                               use_lcp_match, runtime_lcp, runtime_lcp_len);
    log_info(class, path)("Archived boot classpath validation: %s", success ? "passed" : "failed");

    if (success && need_to_check_app_classpath()) {
      success = check_classpaths(false, has_aot_linked_classes, app_cp_start_index(), app_cp_end_index(), all_css.app_cp(),
                                 use_lcp_match, runtime_lcp, runtime_lcp_len);
      log_info(class, path)("Archived app classpath validation: %s", success ? "passed" : "failed");
    }

    if (success) {
      success = check_module_paths(has_aot_linked_classes, module_path_start_index(), module_path_end_index(),
                                   all_css.module_path(), has_extra_module_paths);
      log_info(class, path)("Archived module path validation: %s%s", success ? "passed" : "failed",
                            (*has_extra_module_paths) ? " (extra module paths found)" : "");
    }

    if (runtime_lcp_len > 0) {
      os::free((void*)runtime_lcp);
    }
  }

  if (success) {
    _runtime_instance = this;
  } else {
    const char* mismatch_msg = "shared class paths mismatch";
    const char* hint_msg = log_is_enabled(Info, class, path) ?
        "" : " (hint: enable -Xlog:class+path=info to diagnose the failure)";
    if (RequireSharedSpaces && !PrintSharedArchiveAndExit) {
      if (CDSConfig::is_dumping_final_static_archive()) {
        aot_log_error(aot)("class path and/or module path are not compatible with the "
                       "ones specified when the AOTConfiguration file was recorded%s", hint_msg);
        vm_exit_during_initialization("Unable to use create AOT cache.", nullptr);
      } else {
        aot_log_error(aot)("%s%s", mismatch_msg, hint_msg);
        MetaspaceShared::unrecoverable_loading_error();
      }
    } else {
      MetaspaceShared::report_loading_error("%s%s", mismatch_msg, hint_msg);
    }
  }
  return success;
}

void AOTClassLocationConfig::log_locations(const char* cache_filename, bool is_write) const {
  if (log_is_enabled(Info, class, path)) {
    LogStreamHandle(Info, class, path) st;
    st.print_cr("%s classpath(s) %s %s (size = %d)",
                is_write ? "Writing" : "Reading",
                is_write ? "into" : "from",
                cache_filename, class_locations()->length());
    print_on(&st);
  }
}

void AOTClassLocationConfig::print() {
  if (CDSConfig::is_dumping_archive()) {
    tty->print_cr("AOTClassLocationConfig::_dumptime_instance = %p", _dumptime_instance);
    if (_dumptime_instance != nullptr) {
      _dumptime_instance->print_on(tty);
    }
  }
  if (CDSConfig::is_using_archive()) {
    tty->print_cr("AOTClassLocationConfig::_runtime_instance = %p", _runtime_instance);
    if (_runtime_instance != nullptr) {
      _runtime_instance->print_on(tty);
    }
  }
}

void AOTClassLocationConfig::print_on(outputStream* st) const {
  const char* type = "boot";
  int n = class_locations()->length();
  for (int i = 0; i < n; i++) {
    if (i >= boot_cp_end_index()) {
      type = "app";
    }
    if (i >= app_cp_end_index()) {
      type = "module";
    }
    const AOTClassLocation* cs = class_location_at(i);
    const char* path;
    if (i == 0) {
      path = ClassLoader::get_jrt_entry()->name();
    } else {
      path = cs->path();
    }
    st->print_cr("(%-6s) [%d] = %s", type, i, path);
  }
}
