// Copyright 2014 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.
package com.google.devtools.build.lib.vfs;

import com.google.common.annotations.VisibleForTesting;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.clock.JavaClock;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
import javax.annotation.Nullable;

/**
 * A FileSystem that does not use any JNI and hence, does not require a shared library be present at
 * execution.
 *
 * <p>Note: Blaze profiler tasks are defined on the system call level - thus we do not distinguish
 * (from profiling perspective) between different methods on this class that end up doing stat()
 * system call - they all are associated with the VFS_STAT task.
 */
@ThreadSafe
public class JavaIoFileSystem extends AbstractFileSystemWithCustomStat {
  private static final LinkOption[] NO_LINK_OPTION = new LinkOption[0];
  // This isn't generally safe; we rely on the file system APIs not modifying the array.
  private static final LinkOption[] NOFOLLOW_LINKS_OPTION =
      new LinkOption[] { LinkOption.NOFOLLOW_LINKS };

  private final Clock clock;

  protected static final String ERR_IS_DIRECTORY = " (Is a directory)";
  protected static final String ERR_DIRECTORY_NOT_EMPTY = " (Directory not empty)";
  protected static final String ERR_FILE_EXISTS = " (File exists)";
  protected static final String ERR_NO_SUCH_FILE_OR_DIR = " (No such file or directory)";
  protected static final String ERR_NOT_A_DIRECTORY = " (Not a directory)";

  public JavaIoFileSystem(DigestHashFunction hashFunction) {
    super(hashFunction);
    this.clock = new JavaClock();
  }

  @VisibleForTesting
  JavaIoFileSystem(Clock clock, DigestHashFunction hashFunction) {
    super(hashFunction);
    this.clock = clock;
  }

  protected File getIoFile(PathFragment path) {
    return new File(path.toString());
  }

  /**
   * Returns a {@link java.nio.file.Path} representing the same path as provided {@code path}.
   *
   * <p>Note: while it's possible to use {@link #getIoFile(PathFragment)} in combination with {@link
   * File#toPath()} to achieve essentially the same, using this method is preferable because it
   * avoids extra allocations and does not lose track of the underlying Java filesystem, which is
   * useful for some in-memory filesystem implementations like JimFS.
   */
  protected java.nio.file.Path getNioPath(PathFragment path) {
    return Paths.get(path.toString());
  }

  private LinkOption[] linkOpts(boolean followSymlinks) {
    return followSymlinks ? NO_LINK_OPTION : NOFOLLOW_LINKS_OPTION;
  }

  @Override
  protected Collection<String> getDirectoryEntries(PathFragment path) throws IOException {
    File file = getIoFile(path);
    String[] entries = null;
    long startTime = Profiler.nanoTimeMaybe();
    try {
      entries = file.list();
      if (entries == null) {
        if (file.exists()) {
          throw new IOException(path + ERR_NOT_A_DIRECTORY);
        } else {
          throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
        }
      }
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_DIR, file.getPath());
    }
    Collection<String> result = new ArrayList<>(entries.length);
    for (String entry : entries) {
      if (!entry.equals(".") && !entry.equals("..")) {
        result.add(entry);
      }
    }
    return result;
  }

  @Override
  protected boolean exists(PathFragment path, boolean followSymlinks) {
    long startTime = Profiler.nanoTimeMaybe();
    try {
      java.nio.file.Path nioPath = getNioPath(path);
      return Files.exists(nioPath, linkOpts(followSymlinks));
    } catch (InvalidPathException e) {
      return false;
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, path.toString());
    }
  }

  @Override
  protected boolean isReadable(PathFragment path) throws IOException {
    File file = getIoFile(path);
    long startTime = Profiler.nanoTimeMaybe();
    try {
      if (!file.exists()) {
        throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
      }
      return file.canRead();
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, file.getPath());
    }
  }

  @Override
  protected boolean isWritable(PathFragment path) throws IOException {
    File file = getIoFile(path);
    long startTime = Profiler.nanoTimeMaybe();
    try {
      if (!file.exists()) {
        if (linkExists(file)) {
          throw new IOException(path + ERR_PERMISSION_DENIED);
        } else {
          throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
        }
      }
      return file.canWrite();
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, file.getPath());
    }
  }

  @Override
  protected boolean isExecutable(PathFragment path) throws IOException {
    File file = getIoFile(path);
    long startTime = Profiler.nanoTimeMaybe();
    try {
      if (!file.exists()) {
        throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
      }
      return file.canExecute();
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, file.getPath());
    }
  }

  @Override
  protected void setReadable(PathFragment path, boolean readable) throws IOException {
    File file = getIoFile(path);
    if (!file.exists()) {
      throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
    }
    file.setReadable(readable);
  }

  @Override
  public void setWritable(PathFragment path, boolean writable) throws IOException {
    File file = getIoFile(path);
    if (!file.exists()) {
      throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
    }
    file.setWritable(writable);
  }

  @Override
  protected void setExecutable(PathFragment path, boolean executable) throws IOException {
    File file = getIoFile(path);
    if (!file.exists()) {
      throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
    }
    file.setExecutable(executable);
  }

  @Override
  public boolean supportsModifications(PathFragment path) {
    return true;
  }

  @Override
  public boolean supportsSymbolicLinksNatively(PathFragment path) {
    return true;
  }

  @Override
  public boolean supportsHardLinksNatively(PathFragment path) {
    return true;
  }

  @Override
  public boolean isFilePathCaseSensitive() {
    return true;
  }

  @Override
  public boolean createDirectory(PathFragment path) throws IOException {
    File file = getIoFile(path);
    if (file.mkdir()) {
      return true;
    }

    if (fileIsSymbolicLink(file)) {
      throw new IOException(path + ERR_FILE_EXISTS);
    }
    if (file.isDirectory()) {
      return false; // directory already existed
    } else if (file.exists()) {
      throw new IOException(path + ERR_FILE_EXISTS);
    } else if (!file.getParentFile().exists()) {
      throw new FileNotFoundException(path.getParentDirectory() + ERR_NO_SUCH_FILE_OR_DIR);
    }
    // Parent directory apparently exists - try to create our directory again.
    if (file.mkdir()) {
      return true; // Everything is fine finally.
    } else if (!file.getParentFile().canWrite()) {
      throw new FileAccessException(path + ERR_PERMISSION_DENIED);
    } else {
      // Parent exists, is writable, yet we can't create our directory.
      throw new FileNotFoundException(path.getParentDirectory() + ERR_NOT_A_DIRECTORY);
    }
  }

  @Override
  public void createDirectoryAndParents(PathFragment path) throws IOException {
    java.nio.file.Path nioPath = getNioPath(path);
    try {
      Files.createDirectories(nioPath);
    } catch (java.nio.file.FileAlreadyExistsException e) {
      // Files.createDirectories will handle this case normally, but if the existing
      // file is a symlink to a directory then it still throws. Swallow this.
      if (!isDirectory(path, /*followSymlinks=*/ true)) {
        throw e;
      }
    }
  }

  private boolean linkExists(File file) {
    String shortName = file.getName();
    File parentFile = file.getParentFile();
    if (parentFile == null) {
      return false;
    }
    String[] filenames = parentFile.list();
    if (filenames == null) {
      return false;
    }
    for (String name : filenames) {
      if (name.equals(shortName)) {
        return true;
      }
    }
    return false;
  }

  @Override
  protected void createSymbolicLink(PathFragment linkPath, PathFragment targetFragment)
      throws IOException {
    java.nio.file.Path nioPath = getNioPath(linkPath);
    try {
      Files.createSymbolicLink(nioPath, Paths.get(targetFragment.getSafePathString()));
    } catch (java.nio.file.FileAlreadyExistsException e) {
      throw new IOException(linkPath + ERR_FILE_EXISTS, e);
    } catch (java.nio.file.AccessDeniedException e) {
      throw new IOException(linkPath + ERR_PERMISSION_DENIED, e);
    } catch (java.nio.file.NoSuchFileException e) {
      throw new FileNotFoundException(linkPath + ERR_NO_SUCH_FILE_OR_DIR);
    }
  }

  @Override
  protected PathFragment readSymbolicLink(PathFragment path) throws IOException {
    java.nio.file.Path nioPath = getNioPath(path);
    long startTime = Profiler.nanoTimeMaybe();
    try {
      String link = Files.readSymbolicLink(nioPath).toString();
      return PathFragment.create(link);
    } catch (java.nio.file.NotLinkException e) {
      throw new NotASymlinkException(path, e);
    } catch (java.nio.file.NoSuchFileException e) {
      throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_READLINK, path.getPathString());
    }
  }

  @Override
  public void renameTo(PathFragment sourcePath, PathFragment targetPath) throws IOException {
    File sourceFile = getIoFile(sourcePath);
    File targetFile = getIoFile(targetPath);
    if (!sourceFile.renameTo(targetFile)) {
      if (!sourceFile.exists()) {
        throw new FileNotFoundException(sourcePath + ERR_NO_SUCH_FILE_OR_DIR);
      }
      if (targetFile.exists()) {
        if (targetFile.isDirectory() && targetFile.list().length > 0) {
          throw new IOException(targetPath + ERR_DIRECTORY_NOT_EMPTY);
        } else if (sourceFile.isDirectory() && targetFile.isFile()) {
          throw new IOException(sourcePath + " -> " + targetPath + ERR_NOT_A_DIRECTORY);
        } else if (sourceFile.isFile() && targetFile.isDirectory()) {
          throw new IOException(sourcePath + " -> " + targetPath + ERR_IS_DIRECTORY);
        } else {
          throw new IOException(sourcePath + " -> " + targetPath  + ERR_PERMISSION_DENIED);
        }
      } else {
        throw new FileAccessException(sourcePath + " -> " + targetPath + ERR_PERMISSION_DENIED);
      }
    }
  }

  @Override
  protected long getFileSize(PathFragment path, boolean followSymlinks) throws IOException {
    long startTime = Profiler.nanoTimeMaybe();
    try {
      return stat(path, followSymlinks).getSize();
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, path.getPathString());
    }
  }

  @Override
  protected boolean delete(PathFragment path) throws IOException {
    java.nio.file.Path nioPath = getNioPath(path);
    long startTime = Profiler.nanoTimeMaybe();
    try {
      return Files.deleteIfExists(nioPath);
    } catch (java.nio.file.DirectoryNotEmptyException e) {
      throw new IOException(path.getPathString() + ERR_DIRECTORY_NOT_EMPTY, e);
    } catch (java.nio.file.AccessDeniedException e) {
      throw new IOException(path.getPathString() + ERR_PERMISSION_DENIED, e);
    } catch (java.nio.file.AtomicMoveNotSupportedException
        | java.nio.file.FileAlreadyExistsException
        | java.nio.file.FileSystemLoopException
        | java.nio.file.NoSuchFileException
        | java.nio.file.NotDirectoryException
        | java.nio.file.NotLinkException e) {
      // All known but unexpected subclasses of FileSystemException.
      throw new IOException(path.getPathString() + ": unexpected FileSystemException", e);
    } catch (java.nio.file.FileSystemException e) {
      // Files.deleteIfExists() throws FileSystemException on Linux if a path component is a file.
      // We caught all known subclasses of FileSystemException so `e` is either an unknown
      // subclass or it is indeed a "Not a directory" error. Non-English JDKs may use a different
      // error message than "Not a directory", so we should not look for that text. Checking the
      // parent directory if it's indeed a directory is unrealiable, because another process may
      // modify it concurrently... but we have no better choice.
      if (e.getClass().equals(java.nio.file.FileSystemException.class)
          && !nioPath.getParent().toFile().isDirectory()) {
        // Hopefully the try-block failed because a parent directory was in fact not a directory.
        // Theoretically it's possible that the try-block failed for some other reason and all
        // parent directories were indeed directories, but another process changed a parent
        // directory into a file after the try-block failed but before this catch-block started, and
        // we return false here losing the real exception in `e`, but we cannot know.
        return false;
      } else {
        throw new IOException(path.getPathString() + ": unexpected FileSystemException", e);
      }
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_DELETE, path.getPathString());
    }
  }

  @Override
  protected long getLastModifiedTime(PathFragment path, boolean followSymlinks) throws IOException {
    File file = getIoFile(path);
    long startTime = Profiler.nanoTimeMaybe();
    try {
      return stat(path, followSymlinks).getLastModifiedTime();
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_STAT, file.getPath());
    }
  }

  protected boolean fileIsSymbolicLink(File file) {
    return Files.isSymbolicLink(file.toPath());
  }

  @Override
  public void setLastModifiedTime(PathFragment path, long newTime) throws IOException {
    File file = getIoFile(path);
    if (!file.setLastModified(
        newTime == Path.NOW_SENTINEL_TIME ? clock.currentTimeMillis() : newTime)) {
      if (!file.exists()) {
        throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
      } else if (!file.getParentFile().canWrite()) {
        throw new FileAccessException(path.getParentDirectory() + ERR_PERMISSION_DENIED);
      } else {
        throw new FileAccessException(path + ERR_PERMISSION_DENIED);
      }
    }
  }

  @Override
  protected byte[] getDigest(PathFragment path) throws IOException {
    String name = path.toString();
    long startTime = Profiler.nanoTimeMaybe();
    try {
      return super.getDigest(path);
    } finally {
      profiler.logSimpleTask(startTime, ProfilerTask.VFS_MD5, name);
    }
  }

  /**
   * Returns the status of a file. See {@link Path#stat(Symlinks)} for specification.
   *
   * <p>The default implementation of this method is a "lazy" one, based on other accessor methods
   * such as {@link #isFile}, etc. Subclasses may provide more efficient specializations. However,
   * we still try to follow Unix-like semantics of failing fast in case of non-existent files (or in
   * case of permission issues).
   */
  @Override
  protected FileStatus stat(PathFragment path, boolean followSymlinks) throws IOException {
    java.nio.file.Path nioPath = getNioPath(path);
    final BasicFileAttributes attributes;
    try {
      attributes =
          Files.readAttributes(nioPath, BasicFileAttributes.class, linkOpts(followSymlinks));
    } catch (java.nio.file.FileSystemException e) {
      throw new FileNotFoundException(path + ERR_NO_SUCH_FILE_OR_DIR);
    }
    FileStatus status =  new FileStatus() {
      @Override
      public boolean isFile() {
        return attributes.isRegularFile() || isSpecialFile();
      }

      @Override
      public boolean isSpecialFile() {
        return attributes.isOther();
      }

      @Override
      public boolean isDirectory() {
        return attributes.isDirectory();
      }

      @Override
      public boolean isSymbolicLink() {
        return attributes.isSymbolicLink();
      }

      @Override
      public long getSize() throws IOException {
        return attributes.size();
      }

      @Override
      public long getLastModifiedTime() throws IOException {
        return attributes.lastModifiedTime().toMillis();
      }

      @Override
      public long getLastChangeTime() {
        // This is the best we can do with Java NIO...
        return attributes.lastModifiedTime().toMillis();
      }

      @Override
      public long getNodeId() {
        // TODO(bazel-team): Consider making use of attributes.fileKey().
        return -1;
      }
    };

    return status;
  }

  @Override
  @Nullable
  protected FileStatus statIfFound(PathFragment path, boolean followSymlinks) {
    try {
      return stat(path, followSymlinks);
    } catch (FileNotFoundException e) {
      // JavaIoFileSystem#stat (incorrectly) only throws FileNotFoundException (because it calls
      // #getLastModifiedTime, which can only throw a FileNotFoundException), so we always hit this
      // codepath. Thus, this method will incorrectly not throw an exception for some filesystem
      // errors.
      return null;
    } catch (IOException e) {
      // If this codepath is ever hit, then this method should be rewritten to properly distinguish
      // between not-found exceptions and others.
      throw new IllegalStateException(e);
    }
  }

  @Override
  protected void createFSDependentHardLink(PathFragment linkPath, PathFragment originalPath)
      throws IOException {
    Files.createLink(
        java.nio.file.Paths.get(linkPath.toString()),
        java.nio.file.Paths.get(originalPath.toString()));
  }
}
