All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tomakehurst.wiremock.common.AbstractFileSource Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/*
 * Copyright (C) 2012-2023 Thomas Akehurst
 *
 * 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.github.tomakehurst.wiremock.common;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.github.tomakehurst.wiremock.security.NotAuthorisedException;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public abstract class AbstractFileSource implements FileSource {

  protected final File rootDirectory;

  protected AbstractFileSource(File rootDirectory) {
    this.rootDirectory = rootDirectory;
  }

  protected abstract boolean readOnly();

  @Override
  public BinaryFile getBinaryFileNamed(final String name) {
    assertFilePathIsUnderRoot(name);
    return new BinaryFile(new File(rootDirectory, name).toURI());
  }

  @Override
  public TextFile getTextFileNamed(String name) {
    assertFilePathIsUnderRoot(name);
    return new TextFile(new File(rootDirectory, name).toURI());
  }

  @Override
  public void createIfNecessary() {
    assertWritable();
    if (rootDirectory.exists() && rootDirectory.isFile()) {
      throw new IllegalStateException(rootDirectory + " already exists and is a file");
    } else if (!rootDirectory.exists()) {
      rootDirectory.mkdirs();
    }
  }

  @Override
  public String getPath() {
    return rootDirectory.getPath();
  }

  @Override
  public URI getUri() {
    return rootDirectory.toURI();
  }

  @Override
  public List listFilesRecursively() {
    assertExistsAndIsDirectory();
    List fileList = new ArrayList<>();
    recursivelyAddFilesToList(rootDirectory, fileList);
    return toTextFileList(fileList);
  }

  private void recursivelyAddFilesToList(File root, List fileList) {
    File[] files = Optional.ofNullable(root.listFiles()).orElse(new File[0]);
    for (File file : files) {
      if (file.isDirectory()) {
        recursivelyAddFilesToList(file, fileList);
      } else {
        fileList.add(file);
      }
    }
  }

  private List toTextFileList(List fileList) {
    return fileList.stream().map(input -> new TextFile(input.toURI())).collect(Collectors.toList());
  }

  @Override
  public void writeTextFile(String name, String contents) {
    writeTextFileAndTranslateExceptions(contents, writableFileFor(name));
  }

  @Override
  public void writeBinaryFile(String name, byte[] contents) {
    writeBinaryFileAndTranslateExceptions(contents, writableFileFor(name));
  }

  @Override
  public void deleteFile(String name) {
    writableFileFor(name).delete();
  }

  @Override
  public boolean exists() {
    return rootDirectory.exists();
  }

  private File writableFileFor(String name) {
    assertExistsAndIsDirectory();
    assertFilePathIsUnderRoot(name);
    assertWritable();
    final File filePath = new File(name);

    if (filePath.isAbsolute()) {
      return filePath;
    } else {
      // Convert to absolute path
      return new File(rootDirectory, name);
    }
  }

  private void assertExistsAndIsDirectory() {
    if (rootDirectory.exists() && !rootDirectory.isDirectory()) {
      throw new RuntimeException(rootDirectory + " is not a directory");
    } else if (!rootDirectory.exists()) {
      throw new RuntimeException(rootDirectory + " does not exist");
    }
  }

  private void assertWritable() {
    if (readOnly()) {
      throw new UnsupportedOperationException("Can't write to read only file sources");
    }
  }

  private void assertFilePathIsUnderRoot(String path) {
    try {
      String rootPath = rootDirectory.getCanonicalPath();

      File file = new File(path);
      String filePath =
          file.isAbsolute()
              ? new File(path).getCanonicalPath()
              : new File(rootDirectory, path).getCanonicalPath();

      if (!Paths.get(filePath).normalize().startsWith(rootPath)) {
        throw new NotAuthorisedException("Access to file " + path + " is not permitted");
      }
    } catch (IOException ioe) {
      throw new NotAuthorisedException("File " + path + " cannot be accessed", ioe);
    }
  }

  private void ensureDirectoryExists(File toFile) throws IOException {
    Path toPath = toFile.toPath();
    if (!java.nio.file.Files.exists(toPath)) {
      Path toParentPath = toPath.getParent();
      java.nio.file.Files.createDirectories(toParentPath);
    }
  }

  private void writeTextFileAndTranslateExceptions(String contents, File toFile) {
    try {
      ensureDirectoryExists(toFile);
      Files.asCharSink(toFile, UTF_8).write(contents);
    } catch (IOException ioe) {
      throw new RuntimeException(ioe);
    }
  }

  private void writeBinaryFileAndTranslateExceptions(byte[] contents, File toFile) {
    try {
      ensureDirectoryExists(toFile);
      Files.write(contents, toFile);
    } catch (IOException ioe) {
      throw new RuntimeException(ioe);
    }
  }

  public static Predicate byFileExtension(final String extension) {
    return input -> input.name().endsWith("." + extension);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy