com.facebook.buck.testutil.FakeProjectFilesystem.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.testutil.FakeProjectFilesystem.java

Source

/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.testutil;

import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteStreams;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.nio.file.FileVisitor;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

// TODO(natthu): Implement methods that throw UnsupportedOperationException.
public class FakeProjectFilesystem extends ProjectFilesystem {

    private static final BasicFileAttributes DEFAULT_FILE_ATTRIBUTES = new BasicFileAttributes() {
        @Override
        public FileTime lastModifiedTime() {
            return null;
        }

        @Override
        public FileTime lastAccessTime() {
            return null;
        }

        @Override
        public FileTime creationTime() {
            return null;
        }

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

        @Override
        public boolean isDirectory() {
            return false;
        }

        @Override
        public boolean isSymbolicLink() {
            return false;
        }

        @Override
        public boolean isOther() {
            return false;
        }

        @Override
        public long size() {
            return 0;
        }

        @Override
        public Object fileKey() {
            return null;
        }
    };

    private final Map<Path, byte[]> fileContents;

    public FakeProjectFilesystem() {
        super(Paths.get("."));
        fileContents = Maps.newHashMap();

        // Generally, tests don't care whether files exist.
        ignoreValidityOfPaths = true;
    }

    private byte[] getFileBytes(Path path) {
        return fileContents.get(path.normalize());
    }

    private void rmFile(Path path) {
        fileContents.remove(path.normalize());
    }

    @Override
    public boolean exists(Path path) {
        return fileContents.containsKey(path.normalize());
    }

    @Override
    public long getFileSize(Path path) throws IOException {
        if (!exists(path)) {
            throw new FileNotFoundException(path.toString());
        }
        return getFileBytes(path).length;
    }

    @Override
    public boolean deleteFileAtPath(Path path) {
        if (exists(path)) {
            rmFile(path);
        }
        return true;
    }

    @Override
    public Properties readPropertiesFile(Path pathToPropertiesFile) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isFile(Path path) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isDirectory(Path path, LinkOption... linkOptions) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void walkFileTree(Path root, FileVisitor<Path> fileVisitor) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void rmdir(Path path) {
        Path normalizedPath = path.normalize();
        for (Iterator<Path> iterator = fileContents.keySet().iterator(); iterator.hasNext();) {
            if (iterator.next().startsWith(normalizedPath)) {
                iterator.remove();
            }
        }
    }

    @Override
    public void mkdirs(Path path) {
    }

    @Override
    public void createParentDirs(Path path) {
    }

    @Override
    public void writeLinesToPath(Iterable<String> lines, Path path) {
        StringBuilder builder = new StringBuilder();
        if (!Iterables.isEmpty(lines)) {
            Joiner.on('\n').appendTo(builder, lines);
            builder.append('\n');
        }
        writeContentsToPath(builder.toString(), path);
    }

    @Override
    public void writeContentsToPath(String contents, Path path) {
        writeBytesToPath(contents.getBytes(Charsets.UTF_8), path);
    }

    @Override
    public void writeBytesToPath(byte[] bytes, Path path) {
        fileContents.put(path.normalize(), Preconditions.checkNotNull(bytes));
    }

    @Override
    public OutputStream newFileOutputStream(Path pathRelativeToProjectRoot) throws IOException {
        // This is a hard API to make testable. We need a hook for when
        // the OutputStream is closed in order to update fileContents.  Do
        // we have to subclass ByteArrayOutputStream to override close()?
        throw new UnsupportedOperationException();
    }

    @Override
    public InputStream newFileInputStream(Path pathRelativeToProjectRoot) throws IOException {
        if (!exists(pathRelativeToProjectRoot)) {
            throw new NoSuchFileException(pathRelativeToProjectRoot.toString());
        }
        return new ByteArrayInputStream(fileContents.get(pathRelativeToProjectRoot.normalize()));
    }

    @Override
    public void copyToPath(final InputStream inputStream, Path path) throws IOException {
        writeBytesToPath(ByteStreams.toByteArray(inputStream), path);
    }

    @Override
    public Optional<String> readFileIfItExists(Path path) {
        if (!exists(path)) {
            return Optional.absent();
        }
        return Optional.of(new String(getFileBytes(path), Charsets.UTF_8));
    }

    @Override
    public Optional<Reader> getReaderIfFileExists(Path path) {
        Optional<String> content = readFileIfItExists(path);
        if (!content.isPresent()) {
            return Optional.absent();
        }
        return Optional.of((Reader) new StringReader(content.get()));
    }

    @Override
    public Optional<String> readFirstLine(Path path) {
        List<String> lines;
        try {
            lines = readLines(path);
        } catch (IOException e) {
            return Optional.absent();
        }

        return Optional.fromNullable(Iterables.get(lines, 0, null));
    }

    @Override
    public List<String> readLines(Path path) throws IOException {
        Optional<String> contents = readFileIfItExists(path);
        if (!contents.isPresent() || contents.get().isEmpty()) {
            return ImmutableList.of();
        }
        String content = contents.get();
        content = content.endsWith("\n") ? content.substring(0, content.length() - 1) : content;
        return Splitter.on('\n').splitToList(content);
    }

    @Override
    public String computeSha1(Path path) throws IOException {
        if (!exists(path)) {
            throw new FileNotFoundException(path.toString());
        }
        return Hashing.sha1().hashBytes(getFileBytes(path)).toString();
    }

    /**
     * TODO(natthu): (1) Also traverse the directories. (2) Do not ignore return value of
     * {@code fileVisitor}.
     */
    @Override
    public void walkRelativeFileTree(Path path, FileVisitor<Path> fileVisitor) throws IOException {
        Preconditions.checkArgument(!fileContents.containsKey(path),
                "FakeProjectFilesystem only supports walkRelativeFileTree over directories.");
        for (Path file : getFilesUnderDir(path)) {
            fileVisitor.visitFile(file, DEFAULT_FILE_ATTRIBUTES);
        }
    }

    public void touch(Path path) {
        writeContentsToPath("", path);
    }

    private Collection<Path> getFilesUnderDir(final Path dirPath) {
        return Collections2.filter(fileContents.keySet(), new Predicate<Path>() {
            @Override
            public boolean apply(Path input) {
                return input.startsWith(dirPath);
            }
        });
    }

    @Override
    public boolean isPathChangeEvent(WatchEvent<?> event) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void copyFolder(Path source, Path target) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void copyFile(Path source, Path target) {
        writeContentsToPath(readFileIfItExists(source).get(), target);
    }

    @Override
    public void createSymLink(Path source, Path target, boolean force) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void createZip(Iterable<Path> pathsToIncludeInZip, File out) {
        throw new UnsupportedOperationException();
    }
}